イントロダクション
Laravelは入力されたデータに対するバリデーションの様々なアプローチを提供しています。Laravelの基本コントローラクラスはパワフルでバラエティー豊かなバリデーションルールを使いHTTPリクエストをバリデーションするために便利な手法を提供している、ValidatesRequests
トレイトをデフォルトで使用しています。
クイックスタート
パワフルなバリデーション機能を学ぶために、フォームバリデーションとユーザーにエラーメッセージを表示する完全な例を見てください。
ルート定義
まず、routes/web.php
ファイルに以下のルートを定義してあるとしましょう。
Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');
GET
のルートは新しいブログポストを作成するフォームをユーザーへ表示し、POST
ルートで新しいブログポストをデータベースへ保存します。
コントローラ作成
次に、これらのルートを処理する簡単なコントローラを見てみましょう。今のところstore
メソッドは空のままです。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* 新ブログポスト作成フォームの表示
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* 新しいブログポストの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// ブログポストのバリデーションと保存コード…
}
}
バリデーションロジック
これで新しいブログポストに対するバリデーションロジックをstore
メソッドに埋め込む準備ができました。そのためには、Illuminate\Http\Request
オブジェクトが提供する、validate
メソッドを使います。バリデーションルールに成功すると、コードは通常通り続けて実行されます。逆にバリデーションに失敗すると、例外が投げられ、ユーザーに対し自動的に適切なエラーレスポンスが返されます。伝統的なHTTPリクエストの場合は、リダイレクトレスポンスが生成され、一方でAJAXリクエストにはJSONレスポンスが返されます。
validate
メソッドをもっとよく理解するため、store
メソッドに取り掛かりましょう。
/**
* 新ブログポストの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// ブログポストは有効
}
ご覧のとおりに、実行したいバリデーションルールをvalidate
メソッドへ渡します。繰り返しますが、バリデーションに失敗すれば、適切なレスポンスが自動的に生成されます。バリデーションに成功すれば、コントローラは続けて通常通り実行されます。
最初のバリデーション失敗時に停止
最初のバリデーションに失敗したら、残りのバリデーションルールの判定を停止したいことも、時々あります。このためには、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',
]);
バリデーションエラー表示
ではやって来たリクエストの入力が指定したバリデーションルールに当てはまらなかった場合はどうなるんでしょう? 既に説明した通り、Laravelは自動的にユーザーを以前のページヘリダイレクトします。付け加えて、バリデーションエラーは全部自動的にフラッシュデータとしてセッションへ保存されます。
GET
ルートのビューへエラーメッセージを明示的に結合する必要がないことに注目してください。これはつまり、Laravelはいつもセッションデータの中にエラーの存在をチェックしており、見つけた場合は自動的に結合しているからです。$errors
変数はIlluminate\Support\MessageBag
のインスタンスです。このオブジェクトの詳細は、ドキュメントを参照してください。
Tip!!
$errors
変数はweb
ミドルウェアグループに所属する、Illuminate\View\Middleware\ShareErrorsFromSession
ミドルウェアによりビューに結合されます。このミドルウェアが適用される場合は、いつでもビューの中で$errors
変数が使えます。$errors
変数はいつでも定義済みであると想定でき、安心して使えます。
この例では、バリデーションに失敗すると、エラーメッセージをビューで表示できるように、コントローラのcreate
メソッドにリダイレクトされることになります。
<!-- /resources/views/post/create.blade.php -->
<h1>ポスト作成</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- ポスト作成フォーム -->
@error
ディレクティブ
@error
Bladeディレクティブは、指定した属性のバリデーションエラーメッセージがあるかを簡単に判定するために使用します。@error
ディレクティブの中でエラーメッセージを表示するために、$message
変数をエコーすることも可能です。
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input id="title" type="text" class="@error('title') is-invalid @enderror">
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
オプションフィールドに対する注意
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
を無効な日付として判定します。
AJAXリクエストとバリデーション
この例ではアプリケーションにデータを送るために伝統的なフォームを使いました。しかし、多くのアプリケーションでAJAXリクエストが使用されています。AJAXリクエストにvalidate
メソッドを使う場合、Laravelはリダイレクトレスポンスを生成しません。代わりにバリデーションエラーを全部含んだJSONレスポンスを生成します。このJSONレスポンスは422
HTTPステータスコードで送られます。
フォームリクエストバリデーション
フォームリクエスト作成
より複雑なバリデーションのシナリオでは、「フォームリクエスト」を生成したほうが良いでしょう。フォームリクエストは、バリデーションロジックを含んだカスタムリクエストクラスです。フォームリクエストクラスを作成するには、make:request
Artisan CLIコマンドを使用します。
php artisan make:request StoreBlogPost
生成されたクラスは、app/Http/Request
ディレクトリへ設置されます。このディレクトリが存在しなくても、make:request
コマンドを実行すれば作成されます。では、バリデーションルールを少しrules
メソッドへ追加してみましょう。
/**
* リクエストに適用するバリデーションルールを取得
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
Tip!!
rules
メソッドの引数として、必要な依存をタイプヒントで指定できます。それらはLaravelのサービスコンテナにより、自動的に依存解決されます。
では、どのようにバリデーションルールを実行するのでしょうか?必要なのは、コントローラのメソッドで、このリクエストをタイプヒントで指定することです。やって来たフォームリクエストはコントローラメソッドが呼び出される前にバリデーションを行います。つまり、コントローラにバリデーションロジックを取っ散らかす必要はありません。
/**
* ブログポストの保存
*
* @param StoreBlogPost $request
* @return Response
*/
public function store(StoreBlogPost $request)
{
// 送信されたリクエストは正しい
// バリデーション済みデータの取得
$validated = $request->validated();
}
バリデーションに失敗すると、前のアドレスにユーザーを戻すために、リダイレクトレスポンスが生成されます。エラーも表示できるように、フラッシュデーターとしてセッションに保存されます。もしリクエストがAJAXリクエストであれば、バリデーションエラーを表現する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!');
}
});
}
フォームリクエストの認可
フォームリクエストクラスはauthorize
メソッドも用意しています。このメソッドでは認証されているユーザーが、指定されたリソースを更新する権限を実際に持っているのかを確認します。たとえば、ユーザーが更新しようとしているブログコメントを実際に所有しているかを判断するとしましょう。
/**
* ユーザーがこのリクエストの権限を持っているかを判断する
*
* @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}');
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',
];
}
バリデーション属性のカスタマイズ
バリデーションメッセージの:attribute
部分をカスタム属性名へ置き換えたい場合は、attributes
メソッドをオーバーライドし、カスタム名を指定してください。
/**
* バリデーションエラーのカスタム属性の取得
*
* @return array
*/
public function attributes()
{
return [
'email' => 'email address',
];
}
バリデータの生成
リクエストのvalidate
メソッドを使用したくない場合は、Validator
ファサードを使用し、バリデータインスタンスを生成する必要があります。
このファサードのmake
メソッドで、新しいバリデータインスタンスを生成します。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
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();
}
// ブログポストの保存処理…
}
}
make
メソッドの第1引数は、バリデーションを行うデータです。第2引数はそのデータに適用するバリデーションルールです。
リクエストのバリデーションが失敗するかを確認した後、セッションにエラーメッセージをフラッシュデータとして保存するためにwithErrors
メソッドが利用できます。このメソッドを使うと、簡単にユーザーに情報を表示できるようにするため、リダイレクトの後でビューに対し$errors
変数を自動的に共有します。withErrors
メソッドはバリデータかMessageBag
、PHPの配列を受け取ります。
自動リダイレクト
バリデータインスタンスを自分で生成したいが、リクエストのvalidate
メソッドが提供する自動リダイレクト機能を使用したい場合は、生成したバリデータインスタンスのvalidate
メソッドを呼び出すこともできます。バリデーションに失敗すると、ユーザーは自動的にリダイレクトされるか、AJAXリクエストの場合は、JSONリクエストが返されます。
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
名前付きエラーバッグ
1ページの中に複数のフォームを入れている場合は、特定のフォームのエラーメッセージを受け取れるように、MessageBag
へ名前を付けてください。withErrors
の第2引数に名前を渡します。
return redirect('register')
->withErrors($validator, 'login');
$errors
変数を使い、名前を付けたMessageBag
インスタンスへアクセスできます。
{{ $errors->login->first('email') }}
バリデーション後のフック
バリデータにはさらに、バリデーションが終了した時点で実行するコールバックを付け加えられます。これにより、追加のバリデーションを行い、さらにエラーメッセージコレクションにエラーメッセージを追加することが簡単にできます。バリデータインスタンスのafter
メソッドを使ってみましょう。
$validator = Validator::make(...);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
//
}
エラーメッセージの操作
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')) {
//
}
カスタムエラーメッセージ
必要であればバリデーションでデフォルトのメッセージの代わりに、カスタムエラーメッセージを使うことができます。カスタムメッセージを指定するにはいくつか方法があります。最初の方法はValidator::make
メソッドの第3引数として、カスタムメッセージを渡す方法です。
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);
この例中の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 e-mail address!',
];
言語ファイルでカスタムメッセージ指定
多くの場合、Validator
に直接カスタムメッセージを渡すよりは言語ファイルに指定したいですよね。ならばresources/lang/xx/validation.php
言語ファイルのcustom
配列にメッセージを追加してください。
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
言語ファイル中のカスタム属性名の指定
バリデーションメッセージの:attribute
部分をカスタムアトリビュート名で置き換えたい場合は、resources/lang/xx/validation.php
言語ファイルのattributes
配列でカスタム名を指定してください。
'attributes' => [
'email' => 'email address',
],
言語ファイルでカスタム値を指定
バリデーションメッセージの:value
部分をその値のカスタム表現へ置き換える必要がある場合も起きます。たとえば、payment_type
がcc
という値であれば、クレジットカード番号ルールを指定する必要があると想像してください。
$request->validate([
'credit_card_number' => 'required_if:payment_type,cc'
]);
このバリデーションルールが通らない場合に、次のようなメッセージが表示されるとします。
The credit card number field is required when payment type is cc.
支払いタイプの値としてcc
の代わりに、validation
言語ファイルの中でvalues
配列を定義することにより、カスタム表現値を指定します。
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
これで、バリデーションルールに失敗した場合、以下のようなメッセージが表示されます。
The credit card number field is required when payment type is credit card.
使用可能なバリデーションルール
使用可能な全バリデーションルールとその機能の一覧です。
accepted
そのフィールドがyes、on、1、trueであることをバリデートします。これは「サービス利用規約」同意のバリデーションに便利です。
active_url
フィールドが、dns_get_record
PHP関数により、有効なAかAAAAレコードであることをバリデートします。
after:日付
フィールドの値が与えられた日付より後であるかバリデーションします。日付はPHPのstrtotime
関数で処理されます。
'start_date' => 'required|date|after:tomorrow'
strtotime
により評価される日付文字列を渡す代わりに、その日付と比較する他のフィールドを指定することもできます。
'finish_date' => 'required|date|after:start_date'
after_or_equal:日付
フィールドが指定した日付以降であることをバリデートします。詳細はafterルールを参照してください。
alpha
フィールドが全部アルファベット文字であることをバリデートします。
alpha_dash
フィールドが全部アルファベット文字と数字、ダッシュ(-)、下線(_)であることをバリデートします。
alpha_num
フィールドが全部アルファベット文字と数字であることをバリデートします。
array
フィールドが配列タイプであることをバリデートします。
bail
バリデーションに初めて失敗した時点で、残りのルールのバリデーションを中止します。
before:日付
フィールドが指定された日付より前であることをバリデートします。日付はPHPのstrtotime
関数で処理されます。さらに、after
ルールと同様に、日付け値の代わりにバリデーション対象のフィールド名を指定することができます。
before_or_equal:日付
フィールドが指定した日付以前であることをバリデートします。日付はPHPのstrtotime
関数で処理されます。さらに、after
ルールと同様に、日付け値の代わりにバリデーション対象のフィールド名を指定することができます。
between:min,max
フィールドが指定された最小値と最大値の間のサイズであることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
boolean
フィールドが論理値として有効であることをバリデートします。受け入れられる入力は、true
、false
、1
、0
、"1"
、"0"
です。
confirmed
フィールドがそのフィールド名+_confirmation
フィールドと同じ値であることをバリデートします。例えば、バリデーションするフィールドがpassword
であれば、同じ値のpassword_confirmation
フィールドが入力に存在していなければなりません。
date
パリデーションされる値はPHP関数のstrtotime
により、有効で相対日付ではないことをバリデートします。
date_equals:日付
バリデーションされる値が、指定した日付と同じことをバリデートします。日付は、PHPのstrtotime
関数へ渡されます。
date_format:フォーマット
バリデーションされる値がフォーマット定義と一致するか確認します。バリデーション時にはdate
かdate_format
のどちらかを使用しなくてはならず、両方はできません。このバリデーションはPHPのDateTimeクラスがサポートするフォーマットをすべてサポートしています。
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\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
],
]);
distinct
対象が配列の時、フィールドに重複した値がないことをバリデートします。
'foo.*.id' => 'distinct'
フィールドがメールアドレスとして正しいことをバリデートします。内部でこのバリデーションルールはメールアドレスの検証にegulias/email-validator
パッケージを使用しています。デフォルトではRFCValidation
バリデータが適用されますが、他のバリデーションスタイルも適用可能です。
'email' => 'email:rfc,dns'
上記の例では、RFCValidation
とDNSCheckValidation
バリデーションを適用しています。適用可能なバリデーションスタイルは、次の通りです。
rfc
:RFCValidation
strict
:NoRFCWarningsValidation
dns
:DNSCheckValidation
spoof
:SpoofCheckValidation
filter
:FilterEmailValidation
filter
バリデーションは内部でPHPのfilter_var
関数を使用しており、Laravel5.8以前の動作を行います。
ends_with:foo,bar,...
フィールドの値が、指定された値で終わることをバリデートします。
exists:テーブル,カラム
フィールドの値が、指定されたデータベーステーブルに存在することをバリデートします。
基本的なExistsルールの使用法
'state' => 'exists:states'
column
オプションを指定しない場合、フィールド名が利用されます。
カスタムカラム名の指定
'state' => 'exists:states,abbreviation'
exists
クエリにデータベース接続を指定する必要があることも多いでしょう。「ドット」記法を用い、テーブル名の前に接続名を付けることで、指定可能です。
'email' => 'exists:connection.staff,email'
バリデーションルールで実行されるクエリをカスタマイズしたい場合は、ルールをスラスラと定義できるRule
クラスを使ってください。下の例では、|
文字を区切りとして使用する代わりに、バリデーションルールを配列として指定しています。
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function ($query) {
$query->where('account_id', 1);
}),
],
]);
file
フィールドがアップロードに成功したファイルであることをバリデートします。
filled
フィールドが存在する場合、空でないことをバリデートします。
gt:field
フィールドが指定したフィールドより大きいことをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、size
ルールと同じ規約により評価します。
gte:field
フィールドが指定したフィールド以上であることをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、size
ルールと同じ規約により評価します。
image
フィールドで指定されたファイルが画像(jpg、png、bmp、gif、svg、webp)であることをバリデートします。
in:foo,bar...
フィールドが指定したリストの中の値に含まれていることをバリデートします。このルールを使用するために配列をimplode
する必要が多くなりますので、ルールを記述的に構築するには、Rule::in
メソッドを使ってください。
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
in_array:他のフィールド.*
フィールドが、他のフィールドの値のどれかであることをバリデートします。
integer
フィールドが整数値であることをバリデートします。
Note: このバリデーションルールは入力が「整数」変数型であるのかを検証するわけではありません。ただ入力が整数で構成された文字列か数値であることを確認します。
ip
フィールドがIPアドレスの形式として正しいことをバリデートします。
ipv4
フィールドがIPv4アドレスの形式として正しいことをバリデートします。
ipv6
フィールドがIPv6アドレスの形式として正しいことをバリデートします。
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:jpeg,bmp,png'
拡張子だけを限定する必要があるとしても、このルールはファイルのMIMEタイプに基づき、ファイルの内容を読み、MIMEタイプを推測することでバリデーションを行います。
MIMEタイプと対応する拡張子の完全なリストは、https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.typesで確認できます。
min:値
フィールドが最小値として指定された値以上であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
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'
のようにです。
注目:
regex
とnot_regex
パターンを使用する場合はルールをパイプ(縦棒)で区切らず、ルールの配列で指定する必要があります。特に正規表現に縦棒を含んでいる場合に該当します。
nullable
フィールドがnull
でも良いことをバリデートします。これは特にnull
値を含む文字列や整数のようなプリミティブをバリデートする場合に便利です。
numeric
フィールドは数値であることをバリデートします。
present
フィールドが存在していることをバリデートしますが、存在していれば空を許します。
regex:正規表現
フィールドが指定された正規表現にマッチすることをバリデートします。
このルールは内部でPHPのpreg_match
関数を使用しています。指定された正規表現は有効なデリミッタも含め、preg_match
で要求されているのと同じ形式に従う必要があります。たとえば、'email' => 'regex:/^.+@.+$/i'
のようにです。
注目:
regex
とnot_regex
パターンを使用する場合はルールをパイプ(縦棒)で区切らず、ルールの配列で指定する必要があります。特に正規表現に縦棒を含んでいる場合に該当します。
required
フィールドが入力データに存在しており、かつ空でないことをバリデートします。フィールドは以下の条件の場合、「空」であると判断されます。
- 値が
null
である。 - 値が空文字列である。
- 値が空の配列か、空の
Countable
オブジェクトである。 - 値がパスのないアップロード済みファイルである。
required_if:他のフィールド,値,...
他のフィールドが値のどれかと一致している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_if
ルールにもっと複雑な条件を指定したい場合は、Rule::requiredIf
メソッドを使用してください。このメソッドは論理値かクロージャを引数に取ります。クロージャが渡された場合、そのクロージャはバリデーション対象が要求されているかを示すため、ture
かfalse
を返す必要があります。
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:他のフィールド,値,...
他のフィールドが値のどれとも一致していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_with:foo,bar,...
指定した他のフィールドが一つでも存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_with_all:foo,bar,...
指定した他のフィールドがすべて存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_without:foo,bar,...
指定した他のフィールドのどれか一つでも存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_without_all:foo,bar,...
指定した他のフィールドがすべて存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
same:フィールド
フィールドが、指定されたフィールドと同じ値であることをバリデートします。
size:値
フィールドは指定された値と同じサイズであることをバリデートします。文字列の場合、値は文字長です。数値項目の場合、値は整数値です。配列の場合、値は配列の個数(count
)です。ファイルの場合、値はキロバイトのサイズです。
starts_with:foo,bar,...
フィールドが、指定した値のどれかで始まることをバリデートします。
string
フィルードは文字列タイプであることをバリデートします。フィールドがnull
であることも許す場合は、そのフィールドにnullable
ルールも指定してください。
timezone
timezone_identifiers_list
PHP関数の値に基づき、フィールドがタイムゾーンとして識別されることをバリデートします。
unique:テーブル,カラム,除外ID,IDカラム
フィールドが、指定されたデータベーステーブルに存在しないことをバリデートします。
カスタムカラム名の指定
column
オプションは、フィールドに対応するデータベースカラムを指定するために使用します。column
オプションを指定しない場合、フィールド名が使用されます。
'email' => 'unique:users,email_address'
カスタムデータベース接続
場合により、バリデータにより生成されるデータベースクエリに、カスタム接続を設定する必要があるかもしれません。上記のバリデーションルール、unique:users
ではクエリに対し、デフォルトデータベース接続が使用されます。これをオーバーライドするにはドット記法で、接続に続けテーブル名を指定してください。
'email' => 'unique:connection.users,email_address'
指定されたIDのuniqueルールを無視する
uniqueチェックで指定したIDを除外したい場合があります。たとえばユーザー名、メールアドレス、それと住所の「プロフィール更新」の状況を考えてください。メールアドレスは一意であることを確認したいと思います。しかし、もしユーザーが名前フィールドだけ変更し、メールフィールドを変更しなければ、そのユーザーが既にそのメールアドレスの所有者として登録されているために起きるバリデーションエラーを避けたいと思うでしょう。
バリデータにユーザーIDを無視するように指示するには、ルールをスラスラと定義できるRule
クラスを使います。以下の例の場合、さらにルールを|
文字を区切りとして使用する代わりに、バリデーションルールを配列として指定しています。
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)であることをバリデートします。
条件付きでルールを追加する
項目存在時のバリデーション
ある状況では、そのフィールドが入力配列の中に存在する場合のみ、バリデーションを実行したいことがあると思います。これを簡単に行うには、sometimes
ルールを追加してください。
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
上の例ではemail
フィールドが、$data
配列の中に存在している場合のみバリデーションが実行されます。
Tip!! フィールドが常に存在しているが、空であることをバリデートする場合は、この追加フィールドに対する注意事項を確認してください。
複雑な条件のバリデーション
時々もっと複雑な条件のロジックによりバリデーションルールを追加したい場合もあります。たとえば他のフィールドが100より大きい場合のみ、指定したフィールドが入力されているかをバリデートしたいときなどです。もしくは2つのフィールドのどちらか一方が存在する場合は、両方共に値を指定する必要がある場合です。こうしたルールを付け加えるのも面倒ではありません。最初にValidator
インスタンスを生成するのは、固定ルールの場合と同じです。
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);
ゲームコレクターのためのWebアプリケーションだと仮定しましょう。ゲームコレクターがアプリケーションに登録する時に、100ゲーム以上所有しているのであれば、なぜそんなに多く持っているのか理由を説明してもらいます。たとえば販売店を運営しているのかも知れませんし、ただ収集家なのかも知れません。この条件付きの要求を追加するためにValidator
インスタンスへ、sometimes
メソッドを使用してください。
$v->sometimes('reason', 'required|max:500', function ($input) {
return $input->games >= 100;
});
sometimes
メソッドの最初の引数は条件付きでバリデーションを行うフィールドの名前です。2つ目の引数は追加したいルールです。3つ目の引数にクロージャが渡され、true
を返したらそのルールは追加されます。このメソッドにより複雑な条件付きのバリデーションが簡単に作成できます。一度に多くのフィールドに、条件付きバリデーションを追加することもできます。
$v->sometimes(['reason', 'cost'], 'required', function ($input) {
return $input->games >= 100;
});
Tip!! クロージャに渡される
$input
パラメーターはIlluminate\Support\Fluent
のインスタンスで、フィールドと入力値にアクセスするためのオブジェクトです。
配列のバリデーション
フォーム入力フィールドの配列をバリデーションするのに苦労する必要はありません。配列中の属性をバリデーションするために「ドット記法」が使えます。たとえば、送信されたHTTPリクエストに、photos[profile]
フィールドが含まれているかをバリデーションするには、次のように行います。
$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 e-mail address',
]
],
カスタムバリデーションルール
ルールオブジェクトの使用
Laravelは様々な便利なバリデーションルールを提供しています。しかし、独自のバリデーションも利用したいでしょう。カスタムバリデーションルールを登録する一つ目の方法は、ルールオブジェクトを使うやり方です。新しいルールオブジェクトを生成するには、make:rule
Artisanコマンドを使用します。このコマンドを使用し、文字列が大文字であることをバリデートするルールを生成してみましょう。Laravelの新しいルールは、app/Rules
ディレクトリに設置されます。
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],
]);
クロージャの使用
アプリケーション全体で一回のみカスタムルールの機能が必要な場合は、ルールオブジェクトの代わりにクロージャが使えます。属性名、属性の値、バリデーション失敗時に返す必要のある$fail
コールバックがクロージャに渡されます。
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function ($attribute, $value, $fail) {
if ($value === 'foo') {
$fail($attribute.' is invalid.');
}
},
],
]);
拡張の使用
カスタムバリデーションルールを登録するもう一つの方法では、Validator
ファサードのextend
メソッドを使用します。カスタムバリデーションルールを登録するために、
サービスプロバイダの中で、このメソッドを使ってみましょう。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* 全アプリケーションサービスの登録
*
* @return void
*/
public function register()
{
//
}
/**
* 全アプリケーションサービスの初期起動
*
* @return void
*/
public function boot()
{
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
}
}
カスタムバリデータのクロージャは4つの引数を取ります。$attribute
はバリデーションをしているフィールド、$value
はその値、$parameters
はルールに渡された引数、最後はValidator
インスタンスです。
クロージャの代わりにextend
メソッドへクラスとメソッドを渡すこともできます。
Validator::extend('foo', 'FooValidator@validate');
エラーメッセージの定義
カスタムルールに対するエラーメッセージを定義する必要もあります。インラインでカスタムエラーの配列を使うか、バリデーション言語ファイルにエントリーを追加するどちらかで行えます。このメッセージは属性とエラーメッセージを指定するだけの一次配列で、「カスタマイズ」した配列を入れてはいけません。
"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// 残りのバリデーションエラーメッセージ…
カスタムバリデーションルールを作成する場合、エラーメッセージのカスタムプレースフォルダも定義したいことがあります。前記の方法でカスタムバリデータを作成し、それからValidator
ファサードのreplacer
メソッドを呼びだしてください。これはサービスプロバイダのboot
メソッドの中で行います。
/**
* 全アプリケーションサービスの初期処理
*
* @return void
*/
public function boot()
{
Validator::extend(...);
Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
return str_replace(...);
});
}
暗黙の拡張
バリデートする属性が存在していない場合か空文字列の場合、カスタム拡張したものも含め通常のバリデーションルールは実行されません。たとえばunique
ルールはnull
値に対して実行されません。
$rules = ['name' => 'unique:users,name'];
$input = ['name' => ''];
Validator::make($input, $rules)->passes(); // true
属性が空であってもルールを実行するということは、その属性が必須であることを暗黙のうちに示しています。このような「暗黙の」拡張を作成するには、Validator::extendImplicit()
メソッドを使います。
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
Note: 「暗黙の」拡張は、単にその属性が必須であるとほのめかしているだけです。属性が存在しない場合や空のときに、実際にバリデーションを失敗と判断するかどうかは、みなさん次第です。
暗黙のルールオブジェクト
属性が空の場合にルールオブジェクトを実行したい場合は、Illuminate\Contracts\Validation\ImplicitRule
インターフェイスを実装してください。このインターフェイスはバリデータの「マーカー(目印)インターフェイス」として動作します。そのため、実装する必要のあるメソッドは含んでいません。