イントロダクション
Laravelは、アプリケーションの受信データをバリデーションするために複数の異なるアプローチを提供します。すべての受信HTTPリクエストで使用可能なvalidate
メソッドを使用するのがもっとも一般的です。しかし、バリデーションに対する他のアプローチについても説明します。
Laravelは、データに適用できる便利で数多くのバリデーションルールを持っており、特定のデータベーステーブルで値が一意であるかどうかをバリデーションする機能も提供します。Laravelのすべてのバリデーション機能に精通できるように、各バリデーションルールを詳しく説明します。
クイックスタート
Laravelの強力なバリデーション機能について学ぶため、フォームをバリデーションし、エラーメッセージをユーザーに表示する完全な例を見てみましょう。この高レベルの概要を読むことで、Laravelを使用して受信リクエストデータをバリデーションする一般的な方法を理解できます。
ルート定義
まず、routes/web.php
ファイルに以下のルートを定義してあるとしましょう。
use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);
GET
のルートは新しいブログポストを作成するフォームをユーザーへ表示し、POST
ルートで新しいブログポストをデータベースへ保存します。
コントローラ作成
次に、これらのルートへの受信リクエストを処理する単純なコントローラを見てみましょう。今のところ、store
メソッドは空のままにしておきます。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* 新ブログポスト作成フォームの表示
*
* @return \Illuminate\View\View
*/
public function create()
{
return view('post.create');
}
/**
* 新しいブログポストの保存
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// ブログポストのバリデーションと保存コード…
}
}
バリデーションロジック
これで、新しいブログ投稿をバリデーションするロジックをstore
メソッドに入力する準備が整いました。これを行うには、Illuminate\Http\Request
オブジェクトによって提供されるvalidate
メソッドを使用します。バリデーションルールにパスすると、コードは正常に実行され続けます。しかし、バリデーションに失敗するとIlluminate\Validation\ValidationException
例外が投げられ、適切なエラーレスポンスが自動的にユーザーに返送されます。
伝統的なHTTPリクエスト処理中にバリデーションが失敗した場合、直前のURLへのリダイレクトレスポンスが生成されます。受信リクエストがXHRリクエストの場合、バリデーションエラーメッセージを含むJSONレスポンスが返されます。
validate
メソッドをもっとよく理解するため、store
メソッドに取り掛かりましょう。
/**
* 新ブログポストの保存
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// ブログポストは有効
}
ご覧のとおり、バリデーションルールはvalidate
メソッドへ渡されます。心配いりません。利用可能なすべてのバリデーションルールは文書化されています。この場合でもバリデーションが失敗したとき、適切な応答が自動的に生成されます。バリデーションにパスすると、コントローラは正常に実行を継続します。
もしくは、バリデーションルールを|
で区切られた一つの文字列の代わりに、ルールの配列で指定することもできます。
$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
さらに、validateWithBag
メソッドを使用して、リクエストをバリデーションした結果のエラーメッセージをnamederrorbag内へ保存できます。
$validatedData = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
最初のバリデーション失敗時に停止
最初のバリデーションに失敗したら、残りのバリデーションルールの判定を停止したいことも、ときどきあります。このためには、bail
ルールを使ってください。
$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
この例の場合、title
属性のunique
ルールに失敗すると、max
ルールはチェックされません。ルールは指定した順番にバリデートされます。
ネストした属性の注意点
受信HTTPリクエストに「ネストされた」フィールドデータが含まれている場合は、「ドット」構文を使用してバリデーションルールでこうしたフィールドを指定できます。
$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
フィールド名にピリオドそのものが含まれている場合は、そのピリオドをバックスラッシュでエスケープし、「ドット」構文として解釈されることを明示的に防げます。
$request->validate([
'title' => 'required|unique:posts|max:255',
'v1\.0' => 'required',
]);
バリデーションエラー表示
では、受信リクエストフィールドが指定したバリデーションルールにパスしない場合はどうなるでしょうか。前述のように、Laravelはユーザーを直前の場所へ自動的にリダイレクトします。さらに、すべてのバリデーションエラーとリクエスト入力は自動的にセッションに一時保持保存されます。
$errors
変数は、web
ミドルウェアグループが提供するIlluminate\View\Middleware\ShareErrorsFromSession
ミドルウェアにより、アプリケーションのすべてのビューで共有されます。このミドルウェアが適用されると、ビューで$errors
変数は常に定義され、$errors
変数が常に使用可能になり、安全・便利に使用できると想定できます。$errors
変数はIlluminate\Support\MessageBag
のインスタンスです。このオブジェクトの操作の詳細は、ドキュメントを確認してください。
この例では、バリデーションに失敗すると、エラーメッセージをビューで表示できるように、コントローラのcreate
メソッドへリダイレクトされることになります。
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Postフォームの作成 -->
エラーメッセージのカスタマイズ
Laravelの組み込みバリデーションルールにはそれぞれエラーメッセージがあり、アプリケーションのresources/lang/en/validation.php
ファイルに登録されています。このファイル内に、各バリデーションルールの翻訳エントリがあります。アプリケーションの要求に基づいて、これらのメッセージを自由に変更できます。
さらに、アプリケーションの言語へメッセージを翻訳するために、このファイルを別の翻訳言語ディレクトリにコピーできます。Laravelのローカリゼーションの詳細については、完全な多言語化ドキュメントをご覧ください。
XHRリクエストとバリデーション
この例では、従来のフォームを使用してデータをアプリケーションに送信しました。ただし、多くのアプリケーションは、JavaScriptを利用したフロントエンドからXHRリクエストを受信します。XHRリクエスト中にvalidate
メソッドを使用すると、Laravelはリダイレクト応答を生成しません。代わりに、Laravelはすべてのバリデーションエラーを含むJSONレスポンスを生成します。このJSONレスポンスは、422
HTTPステータスコードとともに送信されます。
@error
ディレクティブ
@error
Bladeディレクティブを使用して、特定の属性にバリデーションエラーメッセージが存在するかどうかを簡単に判断できます。@error
ディレクティブ内で、$message
変数をエコーしてエラーメッセージを表示ができます。
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input id="title" type="text" name="title" class="@error('title') is-invalid @enderror">
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
名前付きエラーバッグを使用している場合は、エラーバッグの名前を
@error
ディレクティブの第2引数へ渡せます。
<input ... class="@error('title', 'post') is-invalid @enderror">
フォームの再取得
Laravelがバリデーションエラーのためにリダイレクトレスポンスを生成するとき、フレームワークは自動的にセッションへのリクエストのすべての入力を一時保持保存します。これは、直後のリクエスト時、保存しておいた入力に簡単にアクセスし、ユーザーが送信しようとしたフォームを再入力・再表示できるようにします。
直前のリクエストから一時保持保存された入力を取得するには、Illuminate\Http\Request
のインスタンスでold
メソッドを呼び出します。old
メソッドは、直前に一時保持保存した入力データをsessionから取り出します。
$title = $request->old('title');
Laravelはグローバルなold
ヘルパも提供しています。Bladeテンプレート内に古い入力を表示している場合は、old
ヘルパを使用してフォームを再入力・再表示する方が便利です。指定されたフィールドに古い入力が存在しない場合、null
が返されます。
<input type="text" name="title" value="{{ old('title') }}">
オプションフィールドに対する注意
LaravelはTrimStrings
とConvertEmptyStringsToNull
ミドルウェアをアプリケーションのデフォルトグローバルミドルウェアスタックに含んでいます。これらのミドルウェアはApp\Http\Kernel
クラスでリストされています。このため、バリデータがnull
値を無効であると判定しないように、オプションフィールドへnullable
を付ける必要が頻繁に起きるでしょう。
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
上記の例の場合、publish_at
フィールドがnull
か、有効な日付表現であることを指定しています。ルール定義にnullable
が追加されないと、バリデータはnull
を無効な日付として判定します。
フォームリクエストバリデーション
フォームリクエスト作成
より複雑なバリデーションシナリオの場合は、「フォームリクエスト」を作成することをお勧めします。フォームリクエストは、独自のバリデーションおよび認可ロジックをカプセル化するカスタムリクエストクラスです。フォームリクエストクラスを作成するには、make:request
Artisan CLIコマンドを使用します。
php artisan make:request StorePostRequest
生成したフォームリクエストクラスは、app/Http/Requests
ディレクトリに配置されます。このディレクトリが存在しない場合は、make:request
コマンドの実行時に作成されます。Laravelにより生成される各フォームリクエストには、authorize
とrules
の2つのメソッドがあります。
ご想像のとおり、authorize
メソッドは、現在認証されているユーザーがリクエストによって表されるアクションを実行できるかどうかを判断し、rules
メソッドはリクエスト中のデータを検証するバリデーションルールを返します。
/**
* リクエストに適用するバリデーションルールを取得
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
Tip!!
rules
メソッドの引数で必要な依存関係をタイプヒントにより指定することができます。それらはLaravelサービスコンテナを介して自動的に依存解決されます。
では、どのようにバリデーションルールを実行するのでしょうか?必要なのはコントローラのメソッドで、このリクエストをタイプヒントで指定することです。やって来たフォームリクエストはコントローラメソッドが呼び出される前にバリデーションを行います。つまり、コントローラでバリデーションロジックを取っ散らかす必要はありません。
/**
* 新しいブログ投稿を保存
*
* @param \App\Http\Requests\StorePostRequest $request
* @return Illuminate\Http\Response
*/
public function store(StorePostRequest $request)
{
// 送信されたリクエストは正しい
// バリデーション済みデータの取得
$validated = $request->validated();
// バリデーション済み入力データの一部を取得
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
}
バリデーションが失敗した場合、リダイレクトレスポンスが生成され、ユーザーを直前の場所に送り返します。エラーもセッションに一時保持され、表示できます。リクエストがXHRリクエストの場合、バリデーションエラーのJSON表現を含む422ステータスコードのHTTPレスポンスがユーザーに返されます。
フォームリクエストへのAfterフックを追加
フォームリクエストに"after"のバリデーションフックを追加する場合は、withValidator
メソッドを使用します。このメソッドは完全に構築されたバリデータを受け取り、バリデーションルールの実際の評価前に、メソッドのいずれでも呼び出せます。
/**
* バリデータインスタンスの設定
*
* @param \Illuminate\Validation\Validator $validator
* @return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
}
最初のバリデーション失敗属性で停止
リクエストクラスにstopOnFirstFailure
プロパティを追加することで、バリデーションの失敗が起きてすぐに、すべての属性のバリデーションを停止する必要があることをバリデータへ指示できます。
/**
* バリデータが最初のルールの失敗で停止するかを指示
*
* @var bool
*/
protected $stopOnFirstFailure = true;
リダイレクト先のカスタマイズ
前述のとおり、フォームリクエストのバリデーションに失敗した場合、ユーザーを元の場所に戻すためのリダイレクトレスポンスが生成されます。しかし、この動作は自由にカスタマイズ可能です。それには、フォームのリクエストで、$redirect
プロパティを定義します。
/**
* バリデーション失敗時に、ユーザーをリダイレクトするURI
*
* @var string
*/
protected $redirect = '/dashboard';
または、ユーザーを名前付きルートへリダイレクトする場合は、$redirectRoute
プロパティを代わりに定義します。
/**
* バリデーション失敗時に、ユーザーをリダイレクトするルート
*
* @var string
*/
protected $redirectRoute = 'dashboard';
フォームリクエストの認可
フォームリクエストクラスには、authorize
メソッドも含まれています。このメソッド内で、認証済みユーザーが特定のリソースを更新する権限を持っているかどうかを判別できます。たとえば、ユーザーが更新しようとしているブログコメントを実際に所有しているかどうかを判断できます。ほとんどの場合、次の方法で認可ゲートとポリシーを操作します。
use App\Models\Comment;
/**
* ユーザーがこのリクエストの権限を持っているかを判断する
*
* @return bool
*/
public function authorize()
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
全フォームリクエストはLaravelのベースリクエストクラスを拡張していますので、現在認証済みユーザーへアクセスする、user
メソッドが使えます。また、上記例中のroute
メソッドの呼び出しにも、注目してください。たとえば{comment}
パラメーターのような、呼び出しているルートで定義してあるURIパラメータにもアクセスできます。
Route::post('/comment/{comment}');
したがって、アプリケーションがルートモデル結合を利用している場合、解決されたモデルをリクエストのプロパティとしてアクセスすることで、コードをさらに簡潔にすることができます。
return $this->user()->can('update', $this->comment);
authorize
メソッドがfalse
を返すと、403ステータスコードのHTTPレスポンスを自動的に返し、コントローラメソッドは実行しません。
アプリケーションの別の部分でリクエストの認可ロジックを処理する場合は、authorize
メソッドからtrue
を返してください。
/**
* ユーザーがこのリクエストの権限を持っているか判断
*
* @return bool
*/
public function authorize()
{
return true;
}
Tip!!
authorize
メソッドの引数で、必要な依存をタイプヒントにより指定できます。それらはLaravelのサービスコンテナにより、自動的に依存解決されます。
エラーメッセージのカスタマイズ
フォームリクエストにより使用されているメッセージはmessage
メソッドをオーバーライドすることによりカスタマイズできます。このメソッドから属性/ルールと対応するエラーメッセージのペアを配列で返してください。
/**
* 定義済みバリデーションルールのエラーメッセージ取得
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
バリデーション属性のカスタマイズ
Laravelの組み込みバリデーションルールエラーメッセージの多くは、:attribute
プレースホルダーを含んでいます。バリデーションメッセージの:attribute
プレースホルダーをカスタム属性名に置き換えたい場合は、attributes
メソッドをオーバーライドしてカスタム名を指定します。このメソッドは、属性と名前のペアの配列を返す必要があります。
/**
* バリデーションエラーのカスタム属性の取得
*
* @return array
*/
public function attributes()
{
return [
'email' => 'email address',
];
}
検証のための入力準備
バリデーションルールを適用する前にリクエストからのデータを準備またはサニタイズする必要がある場合は、prepareForValidation
メソッド使用します。
use Illuminate\Support\Str;
/**
* バリーデーションのためにデータを準備
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}
バリデータの生成
リクエストのvalidate
メソッドを使用したくない場合は、Validator
ファサードを使用し、バリデータインスタンスを生成する必要があります。
このファサードのmake
メソッドで、新しいバリデータインスタンスを生成します。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* 新しいブログポストの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
// バリデーション済みデータの取得
$validated = $validator->validated();
// バリデーション済みデータの一部を取得
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// ブログポストの保存処理…
}
}
make
メソッドの第1引数は、バリデーションを行うデータです。第2引数はそのデータに適用するバリデーションルールの配列です。
リクエストのバリデーションが失敗したかどうかを判断した後、withErrors
メソッドを使用してエラーメッセージをセッションに一時保持保存できます。この方法を使用すると、リダイレクト後に$errors
変数がビューと自動的に共有されるため、メッセージをユーザーへ簡単に表示できます。withErrors
メソッドは、バリデータ、MessageBag
、またはPHPのarray
を引数に取ります。
最初のバリデート失敗時に停止
stopOnFirstFailure
メソッドは、バリデーションが失敗したら、すぐにすべての属性のバリデーションを停止する必要があることをバリデータへ指示します。
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}
自動リダイレクト
バリデータインスタンスを手動で作成するが、HTTPリクエストのvalidate
メソッドによって提供される自動リダイレクトを利用したい場合は、既存のバリデータインスタンスでvalidate
メソッドを呼び出すことができます。バリデーションが失敗した場合、ユーザーは自動的にリダイレクトされます。XHRリクエストの場合は、JSONレスポンスが返されます。
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
validateWithBag
メソッドを使用しリクエストのバリデートを行った結果、失敗した場合に、エラーメッセージを名前付きエラーバッグへ保存することもできます。
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validateWithBag('post');
名前付きエラーバッグ
1つのページに複数のフォームがある場合は、バリデーションエラーを含むMessageBag
に名前を付けて、特定のフォームのエラーメッセージを取得可能にできます。これを実現するには、withErrors
の2番目の引数として名前を渡します。
return redirect('register')->withErrors($validator, 'login');
$errors
変数を使い、名前を付けたMessageBag
インスタンスへアクセスできます。
{{ $errors->login->first('email') }}
エラーメッセージのカスタマイズ
必要に応じて、Laravelが提供するデフォルトのエラーメッセージの代わりにバリデータインスタンスが使用するカスタムエラーメッセージを指定できます。カスタムメッセージを指定する方法はいくつかあります。まず、カスタムメッセージをvalidator::make
メソッドに3番目の引数として渡す方法です。
$validator = Validator::make($input, $rules, $messages = [
'required' => 'The :attribute field is required.',
]);
この例の、:attribute
プレースホルダーは、バリデーション中のフィールドの名前に置き換えられます。バリデーションメッセージには他のプレースホルダーも利用できます。例をご覧ください。
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute value :input is not between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
特定の属性に対するカスタムメッセージ指定
特定の属性に対してのみカスタムエラーメッセージを指定したい場合があります。「ドット」表記を使用してこれを行うことができます。最初に属性の名前を指定し、次にルールを指定します。
$messages = [
'email.required' => 'We need to know your email address!',
];
カスタム属性値の指定
Laravelの組み込みエラーメッセージの多くには、バリデーション中のフィールドや属性の名前に置き換えられる:attribute
プレースホルダーが含まれています。特定のフィールドでこれらのプレースホルダーを置き換える値をカスタマイズするには、カスタム属性表示名の配列を4番目の引数としてValidator::make
メソッドに渡します。
$validator = Validator::make($input, $rules, $messages, [
'email' => 'email address',
]);
バリデーション後のフック
バリデーションが完了した後に実行するコールバックを添付することもできます。これにより、追加のバリデーションを簡単に実行し、メッセージコレクションにエラーメッセージを追加することもできます。利用するには、バリデータインスタンスでafter
メソッドを呼び出します。
$validator = Validator::make(...);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field', 'Something is wrong with this field!'
);
}
});
if ($validator->fails()) {
//
}
バリデーション済み入力の利用
フォームのリクエストや手動で作成したバリデータのインスタンスを使って
リクエストデータをバリデーションした後に、バリデーション済みの受信リクエストデータを取得したいと思われるかもしれません。これには方法がいくつかあります。まず、フォームのリクエストやバリデータインスタンスのvalidated
メソッドを呼び出す方法です。このメソッドは、バリデーション済みデータの配列を返します。
$validated = $request->validated();
$validated = $validator->validated();
他に、フォームリクエストやバリデータのインスタンスに対して、safe
メソッドを呼び出すこともできます。このメソッドは、Illuminate\Support\ValidatedInput
のインスタンスを返します。このオブジェクトはonly
、except
、all
メソッドを用意しており、バリデーション済みデータのサブセットや配列全体を取得できます。
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();
さらに、Illuminate\Support\ValidatedInput
インスタンスをループで配列のようにアクセスすることもできます。
// バリデーション済みデータをループ
foreach ($request->safe() as $key => $value) {
//
}
// バリデーション済みデータを配列としてアクセス
$validated = $request->safe();
$email = $validated['email'];
バリデーション済みデータへさらにフィールドを追加したい場合は、merge
メソッドを呼び出します。
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);
バリデーション済みデータをコレクションインスタンスとして取得したい場合は、collect
メソッドを呼び出します。
$collection = $request->safe()->collect();
エラーメッセージの操作
Validator
インスタンスのerrors
メソッドを呼び出すと、エラーメッセージを操作する便利なメソッドを数揃えた、Illuminate\Support\MessageBag
インスタンスを受け取ります。自動的に作成され、すべてのビューで使用できる$errors
変数も、MessageBag
クラスのインスタンスです。
指定フィールドの最初のエラーメッセージ取得
指定したフィールドの最初のエラーメッセージを取得するには、first
メソッドを使います。
$errors = $validator->errors();
echo $errors->first('email');
指定フィールドの全エラーメッセージ取得
指定したフィールドの全エラーメッセージを配列で取得したい場合は、get
メソッドを使います。
foreach ($errors->get('email') as $message) {
//
}
配列形式のフィールドをバリデーションする場合は、*
文字を使用し、各配列要素の全メッセージを取得できます。
foreach ($errors->get('attachments.*') as $message) {
//
}
全フィールドの全エラーメッセージ取得
全フィールドの全メッセージの配列を取得したい場合は、all
メソッドを使います。
foreach ($errors->all() as $message) {
//
}
指定フィールドのメッセージ存在確認
has
メソッドは、指定したフィールドのエラーメッセージが存在しているかを判定するために使います。
if ($errors->has('email')) {
//
}
言語ファイルでのカスタムメッセージの指定
Laravelの各組み込みバリデーションルールには、アプリケーションのresources/lang/en/validation.php
ファイルにエラーメッセージが用意されています。このファイル内に、各バリデーションルールの翻訳エントリがあります。アプリケーションのニーズに基づいて、これらのメッセージを自由に変更または変更できます。
さらに、このファイルを別の翻訳言語ディレクトリにコピーして、アプリケーションの言語のメッセージを翻訳できます。Laravelのローカリゼーションの詳細については、完全な多言語化ドキュメントをご覧ください。
特定の属性のカスタムメッセージ
アプリケーションのバリデーション言語ファイル内で、属性とルールの組み合わせを指定して、エラーメッセージをカスタマイズできます。これを行うには、カスタマイズメッセージをアプリケーションのresources/lang/xx/validation.php
言語ファイルのcustom
配列へ追加します。
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],
言語ファイルでの属性の指定
Laravelの組み込みエラーメッセージの多くには、バリデーション中のフィールドまたは属性の名前に置き換えられる:attribute
プレースホルダーが含まれています。バリデーションメッセージの:attribute
部分をカスタム値に置き換えたい場合は、resources/lang/xx/validation.php
言語ファイルのattributes
配列でカスタム属性名を指定してください。
'attributes' => [
'email' => 'email address',
],
言語ファイルでの値の指定
Laravelの組み込みバリデーションルールエラーメッセージの一部には、リクエスト属性の現在の値に置き換えられる:value
プレースホルダーが含まれています。ただし、バリデーションメッセージの:value
部分を値のカスタム表現へ置き換えたい場合があるでしょう。たとえば、payment_type
の値がcc
の場合にクレジットカード番号が必要であることを定義する次のルールについて考えてみます。
Validator::make($request->all(), [
'credit_card_number' => 'required_if:payment_type,cc'
]);
このバリデーションルールが通らない場合に、次のようなメッセージが表示されるとします。
The credit card number field is required when payment type is cc.
支払いタイプの値としてcc
を表示する代わりに、values
配列を定義することにより、resources/lang/xx/validation.php
言語ファイルでよりユーザーフレンドリーな値表現が指定できます。
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
この値を定義したら、バリデーションルールは次のエラーメッセージを生成します。
The credit card number field is required when payment type is credit card.
使用可能なバリデーションルール
使用可能な全バリデーションルールとその機能の一覧です。
accepted
フィールドが、"yes"
、"on"
、1
、またはtrue
であることをバリデートします。これは、「利用規約」の承認または同様のフィールドをバリデーションするのに役立ちます。
accepted_if:他のフィールド,値,...
他のフィールドが指定した値と等しい場合、このフィールドは
"yes"
、"on"
、1
、true
であることをバリデートします。これは、"Terms
of Service
"の了承や似たようなフィールドをバリデートするのに便利です。
active_url
フィールドが、dns_get_record
PHP関数により、有効なAかAAAAレコードであることをバリデートします。dns_get_record
へ渡す前に、parse_url
PHP関数により指定したURLのホスト名を切り出します。
after:日付
フィールドは、指定された日付以降の値であることをバリデートします。日付を有効なDateTime
インスタンスに変換するため、strtotime
PHP関数に渡します。
'start_date' => 'required|date|after:tomorrow'
strtotime
により評価される日付文字列を渡す代わりに、その日付と比較する他のフィールドを指定することもできます。
'finish_date' => 'required|date|after:start_date'
after_or_equal:日付
フィールドが指定した日付以降であることをバリデートします。詳細はafterルールを参照してください。
alpha
フィールドが全部アルファベット文字であることをバリデートします。
alpha_dash
フィールドが全部アルファベット文字と数字、ダッシュ(-)、下線(_)であることをバリデートします。
alpha_num
フィールドが全部アルファベット文字と数字であることをバリデートします。
array
フィールドがPHPの配列タイプであることをバリデートします。
array
ルールに追加の値を指定する場合、入力配列の各キーは、ルールに指定した値のリスト内に存在する必要があります。次の例では、入力配列のadmin
キーは、array
ルールにした値のリストに含まれていないので、無効です。
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:username,locale',
]);
一般的に、配列内に存在することが許される配列キーを常に指定する必要があります。そうしないと、バリデータのvalidate
とvalidated
メソッドは他のネストした配列バリデーションルールにより検証されていなくても、配列とそのすべてのキーを含むバリデーション済みデータをすべて返してしまうことになります。
必要に応じ、許可するキーのリストを指定せずにarray
ルールを使用した場合でも、Laravelのバリデータが返す「検証済み」データに未検証の配列キーを含めないように指示できます。そうするには、アプリケーションのAppServiceProvider
のboot
メソッドでバリデータのexcludeUnvalidatedArrayKeys
メソッドを呼び出してください。それによりバリデータは、ネストする配列ルールにより検証された場合にのみ返される「検証済み」データへ配列キーを含めます。
use Illuminate\Support\Facades\Validator;
/**
* 全アプリケーションサービスの登録
*
* @return void
*/
public function boot()
{
Validator::excludeUnvalidatedArrayKeys();
}
bail
フィールドでバリデーションにはじめて失敗した時点で、残りのルールのバリデーションを中止します。
bail
ルールはバリデーションが失敗したときに、特定のフィールドのバリデーションのみを停止するだけで、一方のstopOnFirstFailure
メソッドは、ひとつバリデーション失敗が発生したら、すべての属性のバリデーションを停止する必要があることをバリデータに指示します。
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}
before:日付
フィールドは、指定された日付より前の値であることをバリデートします。日付を有効なDateTime
インスタンスへ変換するために、PHPのstrtotime
関数へ渡します。さらに、after
ルールと同様に、バリデーション中の別のフィールドの名前をdate
の値として指定できます。
before_or_equal:日付
フィールドは、指定された日付より前または同じ値であることをバリデートします。日付を有効なDateTime
インスタンスへ変換するために、PHPのstrtotime
関数へ渡します。さらに、after
ルールと同様に、バリデーション中の別のフィールドの名前をdate
の値として指定できます。
between:min,max
フィールドが指定された最小値と最大値の間のサイズであることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
boolean
フィールドが論理値として有効であることをバリデートします。受け入れられる入力は、true
、false
、1
、0
、"1"
、"0"
です。
confirmed
フィールドが、{field}_confirmation
フィールドと一致する必要があります。たとえば、バリデーション中のフィールドが「password」の場合、「password_confirmation」フィールドが入力に存在し一致している必要があります。
current_password
フィールドが、認証されているユーザーのパスワードと一致することをバリデートします。ルールの最初のパラメータで、認証ガードを指定できます。
'password' => 'current_password:api'
date
パリデーションされる値はPHP関数のstrtotime
により、有効で相対日付ではないことをバリデートします。
date_equals:日付
フィールドが、指定した日付と同じことをバリデートします。日付を有効なDateTime
インスタンスに変換するために、PHPのstrtotime
関数へ渡します。
date_format:フォーマット
バリデーションされる値がフォーマット定義と一致するか確認します。バリデーション時にはdate
かdate_format
のどちらかを使用しなくてはならず、両方はできません。このバリデーションはPHPのDateTimeクラスがサポートするフォーマットをすべてサポートしています。
declined
フィールドが"no"
、"off"
、0
、false
であることをバリデートします。
declined_if:他のフィールド,値,...
他のフィールドが指定した値と等しい場合、このフィールドは"no"
,
"off"
, 0
, or
false
であることをバリデートします。
different:フィールド
フィールドが指定されたフィールドと異なった値を指定されていることをバリデートします。
digits:値
フィールドが数値で、値の桁数であることをバリデートします。
digits_between:最小値,最大値
フィールドが整数で、桁数が最小値から最大値の間であることをバリデートします。
dimensions
バリデーション対象のファイルが、パラメータにより指定されたサイズに合致することをバリデートします。
'avatar' => 'dimensions:min_width=100,min_height=200'
使用可能なパラメータは、min_width、max_width、min_height、max_height、width_、**_height、ratio**です。
ratio制約は、幅を高さで割ったものとして表す必要があります。これは、3/2
のような分数または1.5
のようなfloatのいずれかで指定します。
'avatar' => 'dimensions:ratio=3/2'
このルールは多くの引数を要求するので、Rule::dimensions
メソッドを使い、記述的にこのルールを構築してください。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
],
]);
distinct
配列のバリデーション時、フィールドに重複した値がないことをバリデートします。
'foo.*.id' => 'distinct'
distinctはデフォルトで緩い比較を使用します。厳密な比較を使用するには、検証ルール定義にstrict
パラメータを追加することができます。
'foo.*.id' => 'distinct:strict'
バリデーションルールの引数にignore_case
を追加して、大文字と小文字の違いを無視するルールを加えられます。
'foo.*.id' => 'distinct:ignore_case'
バリデーション中のフィールドは、電子メールアドレスのフォーマットである必要があります。このバリデーションルールは、egulias/email-validator
パッケージを使用して電子メールアドレスをバリデーションします。デフォルトではRFCValidation
バリデータが適用されますが、他のバリデーションスタイルを適用することもできます。
'email' => 'email:rfc,dns'
上記の例では、RFCValidation
とDNSCheckValidation
バリデーションを適用しています。適用可能なバリデーションスタイルは、次の通りです。
rfc
:RFCValidation
strict
:NoRFCWarningsValidation
dns
:DNSCheckValidation
spoof
:SpoofCheckValidation
filter
:FilterEmailValidation
PHPのfilter_var
関数を使用するfilter
バリデータは、Laravelに付属しており、Laravelバージョン5.8より前のLaravelのデフォルトの電子メールバリデーション動作でした。
Note:
dns
およびspoof
バリデータには、PHPのintl
拡張が必要です。
ends_with:foo,bar,...
フィールドの値が、指定された値で終わることをバリデートします。
enum
Enum
ルールはクラスベースのルールで、対象のフィールドに有効なenumの値が含まれているかどうかをバリデートします。Enum
ルールは、コンストラクタの引数に唯一、enumの名前を取ります。
use App\Enums\ServerStatus;
use Illuminate\Validation\Rules\Enum;
$request->validate([
'status' => [new Enum(ServerStatus::class)],
]);
Note: Enumは、PHPバージョン8.1以上でのみ使用可能です。
exclude
フィルードの値がvalidate
とvalidated
メソッドが返すリクエストデータから除外されていることをバリデートします。
exclude_if:他のフィールド,値
他のフィールドが値と等しい場合、validate
とvalidated
メソッドが返すリクエストデータから、バリデーション指定下のフィールドが除外されます。
exclude_unless:他のフィールド,値
他のフィールドが値と等しくない場合、validate
とvalidated
メソッドが返すリクエストデータから、バリデーション指定下のフィールドが除外されます。もし値がnull
(exclude_unless:name,null
)の場合は、比較フィールドがnull
であるか、比較フィールドがリクエストデータに含まれていない限り、バリデーション指定下のフィールドは除外されます。
exclude_without:他のフィールド
他のフィールドが存在しない場合、validate
とvalidated
メソッドが返すリクエストデータから、バリデーション指定下のフィールドが除外されます。
exists:テーブル,カラム
フィールドは、指定のデータベーステーブルに存在する必要があります。
基本的なExistsルールの使用法
'state' => 'exists:states'
column
オプションが指定されていない場合、フィールド名が使用されます。したがって、この場合、ルールは、states
データベーステーブルに、リクエストのstate
属性値と一致するstate
カラム値を持つレコードが含まれていることをバリデーションします。
カスタムカラム名の指定
データベーステーブル名の後に配置することで、バリデーションルールで使用するデータベースカラム名を明示的に指定できます。
'state' => 'exists:states,abbreviation'
場合によっては、exists
クエリに使用する特定のデータベース接続を指定する必要があります。これは、接続名をテーブル名の前に付けることで実現できます。
'email' => 'exists:connection.staff,email'
テーブル名を直接指定する代わりに、Eloquentモデルを指定することもできます。
'user_id' => 'exists:App\Models\User,id'
バリデーションルールで実行されるクエリをカスタマイズしたい場合は、ルールをスラスラと定義できるRule
クラスを使ってください。下の例では、|
文字を区切りとして使用する代わりに、バリデーションルールを配列として指定しています。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function ($query) {
return $query->where('account_id', 1);
}),
],
]);
file
フィールドがアップロードに成功したファイルであることをバリデートします。
filled
フィールドが存在する場合、空でないことをバリデートします。
gt:field
フィールドが指定したフィールドより大きいことをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、size
ルールと同じ規約により評価します。
gte:field
フィールドが指定したフィールド以上であることをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、size
ルールと同じ規約により評価します。
image
ファイルは画像(jpg、jpeg、png、bmp、gif、svg、webp)である必要があります。
in:foo,bar...
フィールドが指定したリストの中の値に含まれていることをバリデートします。このルールを使用するために配列をimplode
する必要が多くなりますので、ルールを記述的に構築するには、Rule::in
メソッドを使ってください。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
in
ルールとarray
ルールを組み合わせた場合、入力配列の各値は、in
ルールに指定した値のリスト内に存在しなければなりません。次の例では,入力配列中のLAS
空港コードは,in
ルールへ指定した空港のリストに含まれていないため無効です。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$input = [
'airports' => ['NYC', 'LAS'],
];
Validator::make($input, [
'airports' => [
'required',
'array',
Rule::in(['NYC', 'LIT']),
],
]);
in_array:他のフィールド.*
フィールドが、他のフィールドの値のどれかであることをバリデートします。
integer
フィールドが整数値であることをバリデートします。
Note: このバリデーションルールは、入力が「整数」変数タイプであるか確認しません。入力がPHPの
FILTER_VALIDATE_INT
ルールで受け入れられるか検証するだけです。入力を数値として検証する必要がある場合は、このルールをnumeric
バリデーションルールと組み合わせて使用してください。
ip
フィールドがIPアドレスの形式として正しいことをバリデートします。
ipv4
フィールドがIPv4アドレスの形式として正しいことをバリデートします。
ipv6
フィールドがIPv6アドレスの形式として正しいことをバリデートします。
mac_address
フィールドがMACアドレスとして正しいことをバリデートします。
json
フィールドが有効なJSON文字列であることをバリデートします。
lt:field
フィールドが指定したフィールドより小さいことをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、size
ルールと同じ規約により評価します。
lte:field
フィールドが指定したフィールド以下であることをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、size
ルールと同じ規約により評価します。
max:値
フィールドが最大値として指定された値以下であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
mimetypes:text/plain,...
フィールドが指定されたMIMEタイプのどれかであることをバリデートします。
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
アップロードしたファイルのMIMEタイプを判別するために、ファイルの内容が読み取られ、フレームワークはMIMEタイプを推測します。これは、クライアントが提供するMIMEタイプとは異なる場合があります。
mimes:foo,bar,...
フィールドで指定されたファイルが拡張子のリストの中のMIMEタイプのどれかと一致することをバリデートします。
MIMEルールの基本的な使用法
'photo' => 'mimes:jpg,bmp,png'
拡張子を指定するだけでもよいのですが、このルールは実際には、ファイルの内容を読み取ってそのMIMEタイプを推測することにより、ファイルのMIMEタイプをバリデーションします。MIMEタイプとそれに対応する拡張子の完全なリストは、次の場所にあります。
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
min:値
フィールドが最小値として指定された値以上であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
multiple_of:値
フィールドが、値の倍数であることをバリデートします。
Note:
multiple_of
ルールを使用するには、bcmath
PHP 拡張機能が必要です。
not_in:foo,bar,...
フィールドが指定された値のリスト中に含まれていないことをバリデートします。Rule::notIn
メソッドのほうが、ルールの構成が読み書きしやすいでしょう。
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);
not_regex:正規表現
フィールドが指定した正規表現と一致しないことをバリデートします。
このルールは内部でPHPのpreg_match
関数を使用しています。パターンは有効なデリミタを使用していることも含め、preg_match
が求めているフォーマットにしたがって指定する必要があります。たとえば:'email' => 'not_regex:/^.+$/i'
Note:
regex
/not_regex
パターンを使用するとき、特に正規表現に|
文字が含まれている場合は、|
区切り文字を使用する代わりに配列を使用してバリデーションルールを指定する必要があります。
nullable
フィールドはnull
であることを許容します。
numeric
フィールドは数値であることをバリデートします。
password
フィールドは、認証済みユーザーのパスワードと一致する必要があります。
Note: このルールはLaravel9で削除するため、
current_password
へ名前を変更しました。代わりに現在のパスワードルールを使用してください。
present
フィールドが存在していることをバリデートしますが、存在していれば空を許します。
prohibited
フィールドが空であるか、存在していないことをバリデートします。
prohibited_if:anotherfield,value,...
anotherfieldフィールドが任意のvalueと等しい場合、対象のフィールドは空であるか、存在しないことをバリデートします。
prohibited_unless:anotherfield,value,...
anotherfielフィールドが任意のvalueと等しくない場合、対象のフィールドは空であるか、存在していないことをバリデートします。
prohibits:anotherfield,...
フィールドが存在する場合、anotherfieldで指定したフィールドが、たとえ空であっても1つも存在していないことをバリデートします。
regex:正規表現
フィールドが指定された正規表現にマッチすることをバリデートします。
このルールは内部でPHPのpreg_match
関数を使用しています。パターンは有効なデリミタを使用していることも含め、preg_match
が求めているフォーマットにしたがって指定する必要があります。たとえば:'email' => 'regex:/^.+@.+$/i'
Note:
regex
/not_regex
パターンを使用するとき、特に正規表現に|
文字が含まれている場合は、|
区切り文字を使用する代わりに、配列でルールを指定する必要があります。
required
フィールドが入力データに存在しており、かつ空でないことをバリデートします。フィールドは以下の条件の場合、「空」であると判断されます。
- 値が
null
である。 - 値が空文字列である。
- 値が空の配列か、空の
Countable
オブジェクトである。 - 値がパスのないアップロード済みファイルである。
required_if:他のフィールド,値,...
他のフィールドが値のどれかと一致している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_if
ルールのより複雑な条件を作成したい場合は、Rule::requiredIf
メソッドを使用できます。このメソッドは、ブール値またはクロージャを受け入れます。クロージャが渡されると、クロージャは「true」または「false」を返し、バリデーション中のフィールドが必要かどうかを示します。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => Rule::requiredIf($request->user()->is_admin),
]);
Validator::make($request->all(), [
'role_id' => Rule::requiredIf(function () use ($request) {
return $request->user()->is_admin;
}),
]);
required_unless:他のフィールド,値,...
他のフィールドが値のどれとも一致していない場合、このフィールドが存在し、かつ空でないことをバリデートします。これは値がnull
でない限り、他のフィールドはリクエストデータに存在しなければならないという意味でもあります。もし値がnull
(required_unless:name,null
)の場合は、比較フィールドがnull
であるか、リクエストデータに比較フィールドが存在しない限り、バリデーション対象下のフィールドは必須です。
required_with:foo,bar,...
指定した他のフィールドが一つでも存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_with_all:foo,bar,...
指定した他のフィールドがすべて存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_without:foo,bar,...
指定した他のフィールドのどれか一つでも存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_without_all:foo,bar,...
指定した他のフィールドがすべて存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
same:フィールド
フィールドが、指定されたフィールドと同じ値であることをバリデートします。
size:値
フィールドは指定された値と同じサイズであることをバリデートします。文字列の場合、値は文字長です。数値項目の場合、値は整数値(属性にnumeric
かinteger
ルールを持っている必要があります)です。配列の場合、値は配列の個数(count
)です。ファイルの場合、値はキロバイトのサイズです。
// 文字列長が12文字ちょうどであることをバリデートする
'title' => 'size:12';
// 指定された整数が10であることをバリデートする
'seats' => 'integer|size:10';
// 配列にちょうど5要素あることをバリデートする
'tags' => 'array|size:5';
// アップロードしたファイルが512キロバイトぴったりであることをバリデートする
'image' => 'file|size:512';
starts_with:foo,bar,...
フィールドが、指定した値のどれかで始まることをバリデートします。
string
フィルードは文字列タイプであることをバリデートします。フィールドがnull
であることも許す場合は、そのフィールドにnullable
ルールも指定してください。
timezone
timezone_identifiers_list
PHP関数の値に基づき、フィールドがタイムゾーンとして識別されることをバリデートします。
unique:テーブル,カラム
フィールドが、指定されたデータベーステーブルに存在しないことをバリデートします。
カスタムテーブル/カラム名の指定
テーブル名を直接指定する代わりに、Eloquentモデルを指定することもできます。
'email' => 'unique:App\Models\User,email_address'
column
オプションは、フィールドの対応するデータベースカラムを指定するために使用します。column
オプションが指定されていない場合、バリデーション中のフィールドの名前が使用されます。
'email' => 'unique:users,email_address'
カスタムデータベース接続の指定
場合により、バリデータが行うデータベースクエリのカスタム接続を指定する必要があります。これには、接続名をテーブル名の前に追加します。
'email' => 'unique:connection.users,email_address'
指定されたIDのuniqueルールを無視する
場合により、uniqueのバリデーション中に特定のIDを無視したいことがあります。たとえば、ユーザーの名前、メールアドレス、および場所を含む「プロファイルの更新」画面について考えてみます。メールアドレスが一意であることを確認したいでしょう。しかし、ユーザーが名前フィールドのみを変更し、メールフィールドは変更しない場合、ユーザーは当該電子メールアドレスの所有者であるため、バリデーションエラーが投げられるのは望ましくありません。
バリデータにユーザーIDを無視するように指示するには、ルールをスラスラと定義できるRule
クラスを使います。以下の例の場合、さらにルールを|
文字を区切りとして使用する代わりに、バリデーションルールを配列として指定しています。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Note: ユーザーがコントロールするリクエストの入力を
ignore
メソッドへ、決して渡してはいけません。代わりに、Eloquentモデルインスタンスの自動増分IDやUUIDのような、生成されたユニークなIDだけを渡してください。そうしなければ、アプリケーションがSQLインジェクション攻撃に対し、脆弱になります。
モデルキーの値をignore
メソッドに渡す代わりに、モデルインスタンス全体を渡すこともできます。Laravelはモデルからキーを自動的に抽出します:
Rule::unique('users')->ignore($user)
もし、テーブルの主キーとしてid
以外のカラム名を使用している場合は、ignore
メソッドを呼び出す時に、カラムの名前を指定してください。
Rule::unique('users')->ignore($user->id, 'user_id')
unique
ルールはデフォルトで、バリデートしようとしている属性名と一致するカラムの同一性をチェックします。しかしながら、unique
メソッドの第2引数として、異なったカラム名を渡すことも可能です。
Rule::unique('users', 'email_address')->ignore($user->id),
追加のWHERE節を付け加える
where
メソッドを使用してクエリをカスタマイズすることにより、追加のクエリ条件を指定できます。たとえば、account_id
列の値が1
の検索レコードのみ検索するクエリ条件で絞り込むクエリを追加してみます。
'email' => Rule::unique('users')->where(function ($query) {
return $query->where('account_id', 1);
})
url
フィールドが有効なURLであることをバリデートします。
uuid
フィールドが有効な、RFC 4122(バージョン1、3、4、5)universally unique identifier (UUID)であることをバリデートします。
条件付きでルールを追加する
フィールドが特定値を持つ場合にバリデーションを飛ばす
他のフィールドに指定値が入力されている場合は、バリデーションを飛ばしたい状況がときどき起きるでしょう。exclude_if
バリデーションルールを使ってください。appointment_date
とdoctor_name
フィールドは、has_appointment
フィールドがfalse
値の場合バリデートされません。
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($data, [
'has_appointment' => 'required|boolean',
'appointment_date' => 'exclude_if:has_appointment,false|required|date',
'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);
もしくは逆にexclude_unless
ルールを使い、他のフィールドに指定値が入力されていない場合は、バリデーションを行わないことも可能です。
$validator = Validator::make($data, [
'has_appointment' => 'required|boolean',
'appointment_date' => 'exclude_unless:has_appointment,true|required|date',
'doctor_name' => 'exclude_unless:has_appointment,true|required|string',
]);
項目存在時のバリデーション
状況によっては、フィールドがバリデーション対象のデータに存在する場合にのみ、フィールドに対してバリデーションチェックを実行したい場合があります。これをすばやく実行するには、sometimes
ルールをルールリストに追加します。
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
上の例ではemail
フィールドが、$data
配列の中に存在している場合のみバリデーションが実行されます。
Tip!! フィールドが常に存在しているが、空であることをバリデートする場合は、この追加フィールドに対する注意事項を確認してください。
複雑な条件のバリデーション
ときどきもっと複雑な条件のロジックによりバリデーションルールを追加したい場合もあります。たとえば他のフィールドが100より大きい場合のみ、指定したフィールドが入力されているかをバリデートしたいときなどです。もしくは2つのフィールドのどちらか一方が存在する場合は、両方共に値を指定する必要がある場合です。こうしたルールを付け加えるのも面倒ではありません。最初にValidator
インスタンスを生成するのは、固定ルールの場合と同じです。
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'games' => 'required|numeric',
]);
私たちのWebアプリケーションがゲームコレクター向けであると仮定しましょう。ゲームコレクターがアプリケーションに登録し、100を超えるゲームを所有している場合は、なぜこれほど多くのゲームを所有しているのかを説明してもらいます。たとえば、ゲームの再販店を経営している場合や、ゲームの収集を楽しんでいる場合などです。この要件を条件付きで追加するには、Validator
インスタンスでsometimes
メソッドを使用できます。
$validator->sometimes('reason', 'required|max:500', function ($input) {
return $input->games >= 100;
});
sometimes
メソッドに渡される最初の引数は、条件付きでバリデーションするフィールドの名前です。2番目の引数は、追加するルールのリストです。3番目の引数として渡すクロージャがtrue
を返す場合、ルールが追加されます。この方法で、複雑な条件付きバリデーションを簡単に作成できます。複数のフィールドに条件付きバリデーションを一度に追加することもできます。
$validator->sometimes(['reason', 'cost'], 'required', function ($input) {
return $input->games >= 100;
});
Tip!! クロージャに渡される
$input
パラメーターは、Illuminate\Support\Fluent
のインスタンスであり、バリデーション中の入力とファイルへアクセスするために使用できます。
複雑な条件の配列バリデーション
インデックスがわからない、入れ子になった同じ配列の中にある別のフィールドに基づいて、あるフィールドを検証したいことがあります。このような場合には、クロージャへ第2引数を渡してください。第2引数には、配列中のバリデーション対象の現アイテムが渡されます。
$input = [
'channels' => [
[
'type' => 'email',
'address' => 'abigail@example.com',
],
[
'type' => 'url',
'address' => 'https://example.com',
],
],
];
$validator->sometimes('channels.*.address', 'email', function ($input, $item) {
return $item->type === 'email';
});
$validator->sometimes('channels.*.address', 'url', function ($input, $item) {
return $item->type !== 'email';
});
クロージャに渡される$input
パラメータと同様に、$item
パラメータは属性データが配列の場合はIlluminate\Support\Fluent
のインスタンス、そうでない場合は文字列になります。
配列のバリデーション
array
バリデーションルールのドキュメントで説明したように、array
ルールは、許可する配列キーのリストを受け入れます。配列内にその他のキーが存在する場合、バリデーションは失敗します。
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:username,locale',
]);
一般的には、配列内に存在を許す配列キーを常に指定する必要があります。そうしないと、バリデータのvalidate
やvalidated
メソッドは、配列とそのすべてのキーを含むバリデート済みデータをすべて返してしまいます。
バリデートできなかった配列キーの除外
必要に応じ、許可するキーのリストを指定せずにarray
ルールを使用した場合でも、Laravelのバリデータが返す「検証済み」データに未検証の配列キーを含めないように指示できます。そうするには、アプリケーションのAppServiceProvider
のboot
メソッドでバリデータのexcludeUnvalidatedArrayKeys
メソッドを呼び出してください。それによりバリデータは、ネストする配列ルールにより検証された場合にのみ返される「検証済み」データへ配列キーを含めます。
use Illuminate\Support\Facades\Validator;
/**
* 全アプリケーションサービスの登録
*
* @return void
*/
public function boot()
{
Validator::excludeUnvalidatedArrayKeys();
}
ネストした配列入力のバリデーション
ネストした配列ベースフォームの入力フィールドをバリデーションするのが、面倒である必要はありません。配列内の属性をバリデーションするには、「ドット記法」が使えます。たとえば、HTTPリクエストにphotos[profile]
フィールドが含まれている場合、次のように検証します。
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);
配列の各要素をバリデーションすることもできます。たとえば、特定の配列入力フィールドの各メールが一意であることをバリデーションするには、次のようにします。
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
同様に、言語ファイルのカスタムバリデーションメッセージを指定するときに*
文字を使用すると、配列ベースのフィールドに単一のバリデーションメッセージを簡単に使用できます。
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique email address',
]
],
パスワードのバリデーション
パスワードが十分なレベルの複雑さがあることを確認するために、LaravelのPassword
ルールオブジェクトを使用できます。
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
$validator = Validator::make($request->all(), [
'password' => ['required', 'confirmed', Password::min(8)],
]);
Password
ルールオブジェクトを使用すると、文字・数字・記号を最低1文字必要にしたり、文字種を組み合わせたりのように、パスワードの指定をアプリケーションで使用する複雑さの要件に合うよう簡単にカスタマイズできます。
// 最低8文字必要
Password::min(8)
// 最低1文字の文字が必要
Password::min(8)->letters()
// 最低大文字小文字が1文字ずつ必要
Password::min(8)->mixedCase()
// 最低一文字の数字が必要
Password::min(8)->numbers()
// 最低一文字の記号が必要
Password::min(8)->symbols()
さらに、uncompromised
メソッドを使って、公開されているパスワードのデータ漏洩によるパスワード漏洩がないことを確認することもできます。
Password::min(8)->uncompromised()
内部的には、Password
ルールオブジェクトは、k-Anonymityモデルを使用して、ユーザーのプライバシーやセキュリティを犠牲にすることなく、パスワードがhaveibeenpwned.comサービスを介してリークされているかを判断します。
デフォルトでは、データリークに少なくとも1回パスワードが表示されている場合は、侵害されたと見なします。uncompromised
メソッドの最初の引数を使用してこのしきい値をカスタマイズできます。
// 同一のデータリークにおいて、パスワードの出現回数が3回以下であることを確認
Password::min(8)->uncompromised(3);
もちろん、上記の例ですべてのメソッドをチェーン化することができます。
Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()
デフォルトパスワードルールの定義
パスワードのデフォルトバリデーションルールをアプリケーションの一箇所で指定できると便利でしょう。クロージャを引数に取るPassword::defaults
メソッドを使用すると、これを簡単に実現できます。defaults
メソッドへ渡すクロージャは、パスワードルールのデフォルト設定を返す必要があります。通常、defaults
ルールはアプリケーションのサービスプロバイダの1つのboot
メソッド内で呼び出すべきです。
use Illuminate\Validation\Rules\Password;
/**
* アプリケーションの全サービスの初期処理
*
* @return void
*/
public function boot()
{
Password::defaults(function () {
$rule = Password::min(8);
return $this->app->isProduction()
? $rule->mixedCase()->uncompromised()
: $rule;
});
}
そして、バリデーションで特定のパスワードへデフォルトルールを適用したい場合に、引数なしでdefaults
メソッドを呼び出します。
'password' => ['required', Password::defaults()],
時には、デフォルトのパスワードバリデーションルールへ追加ルールを加えたい場合があります。このような場合には、rules
メソッドを使用します。
use App\Rules\ZxcvbnRule;
Password::defaults(function () {
$rule = Password::min(8)->rules([new ZxcvbnRule]);
// ...
});
カスタムバリデーションルール
ルールオブジェクトの使用
Laravelは有用な数多くのバリデーションルールを提供しています。ただし、独自のものを指定することもできます。カスタムバリデーションルールを登録する1つの方法は、ルールオブジェクトを使用することです。新しいルールオブジェクトを生成するには、make:rule
Artisanコマンドを使用できます。このコマンドを使用して、文字列が大文字であることを確認するルールを生成してみましょう。Laravelは新しいルールをapp/Rules
ディレクトリに配置します。このディレクトリが存在しない場合、Artisanコマンドを実行してルールを作成すると、Laravelがそのディレクトリを作成します。
php artisan make:rule Uppercase
ルールを生成したら、動作を定義する準備ができました。ルールオブジェクトは2つのメソッドを含みます。passes
とmessage
です。passes
メソッドは属性の値と名前を受け取り、その属性値が有効であればtrue
、無効であればfalse
を返します。message
メソッドは、バリデーション失敗時に使用する、バリデーションエラーメッセージを返します。
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{
/**
* バリデーションの成功を判定
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return strtoupper($value) === $value;
}
/**
* バリデーションエラーメッセージの取得
*
* @return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}
もちろん、翻訳ファイルのエラーメッセージを返したい場合は、message
メソッドからtrans
ヘルパを呼び出せます。
/**
* バリデーションエラーメッセージの取得
*
* @return string
*/
public function message()
{
return trans('validation.uppercase');
}
ルールが定義できたら、他のバリデーションルールと一緒に、ルールオブジェクトのインスタンスをバリデータへ渡し、指定します。
use App\Rules\Uppercase;
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);
追加データへのアクセス
カスタムバリデーションルールクラスがバリデーション下の他のすべてのデータへアクセスする必要がある場合、そのルールクラスにIlluminate\Contracts\Validation\DataAwareRule
インターフェイスを実装してください。このインターフェイスは、クラスへsetData
メソッドの定義を要求します。このメソッドはLaravelにより自動的に(バリデーション処理前に)、バリデーション対象の全データで呼び出されます。
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\DataAwareRule;
class Uppercase implements Rule, DataAwareRule
{
/**
* バリデーション下の全データ
*
* @var array
*/
protected $data = [];
// ...
/**
* バリデーション下のデータをセット
*
* @param array $data
* @return $this
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
}
または、バリデーションルールが、バリデーションを行うバリデータインスタンスへのアクセスを必要とする場合は、ValidatorAwareRule
インターフェイスを実装してください。
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
class Uppercase implements Rule, ValidatorAwareRule
{
/**
* バリデータインスタンス
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
// ...
/**
* 現用バリデータのセット
*
* @param \Illuminate\Validation\Validator $validator
* @return $this
*/
public function setValidator($validator)
{
$this->validator = $validator;
return $this;
}
}
クロージャの使用
アプリケーション全体でカスタムルールの機能が1回だけ必要な場合は、ルールオブジェクトの代わりにクロージャを使用できます。クロージャは、属性の名前、属性の値、およびバリデーションが失敗した場合に呼び出す必要がある$fail
コールバックを受け取ります。
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function ($attribute, $value, $fail) {
if ($value === 'foo') {
$fail('The '.$attribute.' is invalid.');
}
},
],
]);
暗黙のルール
デフォルトでは、バリデーションされる属性が存在しないか、空の文字列が含まれている場合、カスタムルールを含む通常のバリデーションルールは実行されません。たとえば、unique
ルールは空の文字列に対して実行されません。
use Illuminate\Support\Facades\Validator;
$rules = ['name' => 'unique:users,name'];
$input = ['name' => ''];
Validator::make($input, $rules)->passes(); // true
属性が空の場合でもカスタムルールを実行するには、ルールは属性が必須であることを意味する必要があります。「暗黙の」ルールを作成するには、Illuminate\Contracts\Validation\ImplicitRule
インターフェイスを実装します。このインターフェイスは、バリデータの「マーカーインターフェイス」として機能します。したがって、通常のRule
インターフェイスで必要なメソッド以外に実装する必要のある追加のメソッドは含まれていません。
新しい暗黙のルールオブジェクトを生成するには、make:rule
Artisanコマンドに--implicit
オプションを付けて使用してください。
php artisan make:rule Uppercase --implicit
Note: 「暗黙の」ルールは、属性が必要であることを暗黙的にします。欠落している属性または空の属性を実際に無効にするかどうかは、あなた次第です。