イントロダクション
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
メソッドに埋め込む準備ができました。アプリケーションの基本コントローラー(App\Http\Controllers\Controller
)クラスを調べてみれば、ValidatesRequests
トレイトを使っているのが分かるでしょう。このトレイトは全てのコントローラーに対して、便利なvalidate
メソッドを提供しています。
validate
メソッドはHTTPリクエストとバリデーションルールを受け取ります。バリデーションに適合するとそのまま続けてコードが実行されます。しかし、バリデーションに失敗すると例外が投げられ、適当なエラーレスポンスが自動的にユーザーに送り返されます。伝統的なHTTPリクエストの場合はリダイレクトが生成され、AJAXリクエストの場合はJSONレスポンスが送られます。
validate
メソッドをもっとよく理解するため、store
メソッドに取り掛かりましょう。
/**
* 新ブログポストの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// ブログポストは有効なので、データベースに保存する処理…
}
ご覧の通り、HTTPリクエストと希望のバリデーションルールをvalidate
メソッドに渡しているだけです。繰り返しますが、バリデーションに失敗すれば、適当なレスポンスが自動的に生成されます。バリデーションに合格すれば、コントローラーは普通に実行されます。
最初のバリデーション失敗時に停止
最初のバリデーションに失敗したら、残りのバリデーションルールの判定を停止したいことも、時にはあります。このためには、bail
ルールを使ってください。
$this->validate($request, [
'title' => 'bail|unique:posts|max:255',
'body' => 'required',
]);
上記の例で、title
属性に対するunique
ルールが失敗したら、max
ルールはチェックされません。ルールは指定された順番にバリデートされます。
ネストした属性の注意点
HTTPリクエストに「ネスト」したパラメーターが含まれている場合、バリデーションルールは「ドット」記法により指定します。
$this->validate($request, [
'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
<!-- ポスト作成フォーム -->
オプションフィールドに対する注意
LaravelはTrimStrings
とConvertEmptyStringsToNull
ミドルウェアをアプリケーションのデフォルトグローバルミドルウェアスタックに含んでいます。これらのミドルウェアはApp\Http\Kernel
クラスでリストされています。このため、バリデータがnull
値が無効であると判定されないように、オプションフィールドへnullable
を付ける必要がたびたび起きるでしょう。
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
上記の例の場合、publish_at
フィールドがnull
か、有効な日付表現であることを指定しています。ルール定義にnullable
が追加されないと、バリデータはnull
を無効な日付として判定します。
フラッシュエラーメッセージのカスタマイズ
バリデーション失敗時にセッションへフラッシュデータとして保存されるバリデーションエラーのフォーマットをカスタマイズしたい場合は、基本コントローラーのformatValidationErrors
をオーバーライドしてください。Illuminate\Contracts\Validation\Validator
クラスをファイルにインポートするのを忘れないでください。
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
abstract class Controller extends BaseController
{
use DispatchesJobs, ValidatesRequests;
/**
* {@inheritdoc}
*/
protected function formatValidationErrors(Validator $validator)
{
return $validator->errors()->all();
}
}
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',
];
}
では、どのようにバリデーションルールを実行するのでしょうか?必要なのは、コントローラーのメソッドで、このリクエストをタイプヒントで指定することです。やって来たフォームリクエストはコントローラーメソッドが呼び出される前にバリデーションを行います。つまり、コントローラーにバリデーションロジックを取っ散らかす必要はありません。
/**
* ブログポストの保存
*
* @param StoreBlogPost $request
* @return Response
*/
public function store(StoreBlogPost $request)
{
// 送られて来たリクエストは正しい
}
バリデーションに失敗すると、前のアドレスにユーザーを戻すために、リダイレクトレスポンスが生成されます。エラーも表示できるように、フラッシュデーターとしてセッションに保存されます。もしリクエストが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;
}
エラーフォーマットのカスタマイズ
バリデーションが失敗した時にフラッシュデーターとして保存されるバリデーションエラーの形式をカスタマイズしたければ、基本コントローラー(App\Http\Requests\Request
)のformatErrors
をオーバーライドしてください。Illuminate\Contracts\Validation\Validator
クラスをファイルの先頭でインポートするのを忘れないでください。
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
エラーメッセージのカスタマイズ
フォームリクエストにより使用されているメッセージはmessage
メソッドをオーバーライドすることによりカスタマイズできます。このメソッドから属性/ルールと対応するエラーメッセージのペアを配列で返してください。
/**
* 定義済みバリデーションルールのエラーメッセージ取得
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
バリデータの生成
ValidatesRequests
トレイトのvalidate
メソッドを使いたくなければ、Validator
ファサードを使い、バリデーターインスタンスを自分で作成してください。このファサードのmake
メソッドで、新しいインスタンスを生成できます。
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
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の配列を受け取ります。
自動リダイレクト
バリデータインスタンスを自分で作成する場合でも、ValidatesRequest
トレイトが提供する自動リダイレクトの利点を利用したい場合は、バリデータインスタンスに存在する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 must be 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',
],
使用可能なバリデーションルール
使用可能な全バリデーションルールとその機能の一覧です。
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:date
フィールドが指定した日付以降であることをバリデートします。詳細はafterルールを参照してください。
alpha
フィールドが全部アルファベット文字であることをバリデートします。
alpha_dash
フィールドが全部アルファベット文字とダッシュ(-)、下線(_)であることをバリデートします。
alpha_num
フィールドが全部アルファベット文字と数字であることをバリデートします。
array
フィールドが配列タイプであることをバリデートします。
before:日付
フィールドが指定された日付より前であることをバリデートします。日付はPHPのstrtotime
関数で処理されます。
before_or_equal:date
フィールドが指定した日付以前であることをバリデートします。日付はPHPのstrtotime
関数で処理されます。
between:min,max
フィールドが指定された最小値と最大値の間のサイズであることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
boolean
フィールドが論理値として有効であることをバリデートします。受け入れられる入力は、true
、false
、1
、0
、"1"
、"0"
です。
confirmed
フィールドがそのフィールド名+_confirmation
フィールドと同じ値であることをバリデートします。例えば、バリデーションするフィールドがpassword
であれば、同じ値のpassword_confirmation
フィールドが入力に存在していなければなりません。
date
パリデーションされる値はPHP関数のstrtotime
を使用し確認されます。
date_format:フォーマット
バリデーションされる値がフォーマット定義と一致するか確認します。バリデーション時にはdate
かdate_format
のどちらかを使用しなくてはならず、両方はできません。
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'
フィールドがメールアドレスとして正しいことをバリデートします。
exists:テーブル,カラム
フィールドの値が、指定されたデータベーステーブルに存在することをバリデートします。
基本的なExistsルールの使用法
'state' => 'exists:states'
カスタムカラム名の指定
'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
フィールドが存在する場合、空でないことをバリデートします。
image
フィールドで指定されたファイルが画像(jpg、png、bmp、gif、svg)であることをバリデートします。
in:foo,bar...
フィールドが指定したリストの中の値に含まれていることをバリデートします。このルールを使用するために配列をimplode
する必要が多くなりますので、ルールを記述的に構築するには、Rule::in
メソッドを使ってください。
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
in_array:別のフィールド
フィールドが、他のフィールドの値のどれかであることをバリデートします。
integer
フィールドが整数値であることをバリデートします。
ip
フィールドがIPアドレスの形式として正しいことをバリデートします。
ipv4
フィールドがIPv4アドレスの形式として正しいことをバリデートします。
ipv6
フィールドがIPv6アドレスの形式として正しいことをバリデートします。
json
フィールドが有効なJSON文字列であることをバリデートします。
max:値
フィールドが最大値として指定された値以下であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
mimetypes:text/plain,...
フィールドが指定されたMIMEタイプのどれかであることをバリデートします。
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
アップロードされたファイルのMIMEタイプを決定するために、フレームワークはその内容を読み込み、MIMEタイプを推測します。クライアントが提供するMIMEタイプとは異なります。
mimes:foo,bar,...
フィールドで指定されたファイルが拡張子のリストの中のMIMEタイプのどれかと一致することをバリデートします。
mimesルールの基本的な使用法
'photo' => 'mimes:jpeg,bmp,png'
拡張子だけを限定する必要があるとしても、このルールはファイルのMIMEタイプに基づき、ファイルの内容を読み、MIMEタイプを推測することでバリデーションを行います。
MIMEタイプと対応する拡張子の完全なリストは、https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.typesで確認できます。
min:値
フィールドが最小値として指定された値以上であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。
nullable
フィールドがnull
であることをバリデートします。これはnull
値を含無ことができる文字列や整数のようなプリミティブをバリデーションするときに特に便利です。
not_in:foo,bar,...
フィールドが指定された値のリスト中に含まれていないことをバリデートします。Rule::notIn
メソッドのほうが、ルールの構成が読み書きしやすいでしょう。
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);
numeric
フィールドは数値であることをバリデートします。
present
フィールドが存在していることをバリデートしますが、存在していれば空を許します。
regex:正規表現
フィールドが指定された正規表現にマッチすることをバリデートします。
注目:
regex
パターンを使用する場合はルールをパイプ(縦棒)で区切らず、配列で指定する必要があります。特に正規表現に縦棒を含んでいる場合に該当します。
required
フィールドが入力データに存在しており、かつ空でないことをバリデートします。フィールドは以下の条件の場合、「空」であると判断されます。
- 値が
null
である。 - 値が空文字列である。
- 値が空の配列か、空の
Countable
オブジェクトである。 - 値がパスのないアップロード済みファイルである。
required_if:他のフィールド,値,...
他のフィールドが値のどれかと一致している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_unless:他のフィールド,値,...
他のフィールドが値のどれとも一致していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_with:foo,bar,...
指定した他のフィールドが一つでも存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_with_all:foo,bar,...
指定した他のフィールドがすべて存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_without:foo,bar,...
指定した他のフィールドのどれか一つでも存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
required_without_all:foo,bar,...
指定した他のフィールドがすべて存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。
same:フィールド
フィールドが、指定されたフィールドと同じ値であることをバリデートします。
size:値
フィールドは指定された値と同じサイズであることをバリデートします。文字列の場合、値は文字長です。数値項目の場合、値は整数値です。配列の場合、値は配列の個数(count
)です。ファイルの場合、値はキロバイトのサイズです。
string
フィルードは文字列タイプであることをバリデートします。フィールドがnull
であることも許す場合は、そのフィールドにnullable
ルールも指定してください。
timezone
timezone_identifiers_list
PHP関数の値に基づき、フィールドがタイムゾーンとして識別されることをバリデートします。
unique:テーブル,カラム,除外ID,IDカラム
フィールドは指定されたデータベーステーブルで一意であることをバリデートします。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),
],
]);
もしテーブルの主キーとして、id
以外のカラム名を使用している場合、ignore
メソッドを呼び出す時に、カラムの名前を指定してください。
'email' => Rule::unique('users')->ignore($user->id, 'user_id')
追加のWHERE節を付け加える
where
メソッドを使用し、クエリをカスタマイズすることにより、追加のクエリ制約を指定することも可能です。例として、account_id
が1
であることを確認する制約を追加してみましょう。
'email' => Rule::unique('users')->where(function ($query) {
$query->where('account_id', 1);
})
url
フィールドが有効なURLであることをバリデートします。
条件付きでルールを追加する
項目存在時のバリデーション
ある状況では、そのフィールドが入力配列の中に存在する場合のみ、バリデーションを実行したいことがあると思います。これを簡単に行うには、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は様々な役に立つバリデーションルールを提供しています。しかし自分自身の特別なルールも使いたいですよね。カスタムバリデーションルールを追加する一つの方法は、Validator
ファサードのextend
を使う方法です。カスタムバリデーションルールを追加するために、サービスプロバイダの中でこのメッセージを使ってみましょう。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* アプリケーションサービスの初期処理
*
* @return void
*/
public function boot()
{
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
}
/**
* サービスプロバイダ登録
*
* @return void
*/
public function register()
{
//
}
}
カスタムバリデーターのクロージャは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(...);
});
}
暗黙の拡張
バリデートする属性が存在していない場合か、required
ルールで定義している「空」の場合、カスタム拡張したものも含め、通常のバリデーションルールは実行されません。たとえばunique
ルールはnull
値に対して実行されません。
$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes(); // true
属性が空であってもルールを実行するということは、その属性が必須であることを暗黙のうちに示しています。このような「暗黙の」拡張を作成するには、Validator::extendImplicit()
メソッドを使います。
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
Note: 「暗黙の」拡張は、単にその属性が必須であるとほのめかしているだけです。属性が存在しない場合や空のときに、実際にバリデーションを失敗と判断するかどうかは、みなさん次第です。