基本の使用法
Laravelにはシンプルで便利なValidation
クラスが用意されており、データーの正当性確認やエラーメッセージの取得ができます。
基本的なバリデーション例
$validator = Validator::make(
['name' => 'Dayle'],
['name' => 'required|min:5']
);
make
メソッドに渡す最初の引数はバリデーションを行うデーターです。2つ目の引数はデーターに適用するバリデーションルールです。
ルールの指定に配列を使用
複数のルール指定はパイプ(縦線)で区切るか、配列で分割し指定します。
$validator = Validator::make(
['name' => 'Dayle'],
['name' => ['required', 'min:5']]
);
複数フィールドのバリデーション
$validator = Validator::make(
[
'name' => 'Dayle',
'password' => 'lamepassword',
'email' => 'email@example.com'
],
[
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users'
]
);
Validator
インスタンスが生成されたら、fails
(もしくはpasses
)メソッドを使用し、バリデーションを実行します。
if ($validator->fails())
{
// 与えられたデーターはバリデーションをパスしなかった
}
バリデーションが失敗すると、バリデーターよりエラーメッセージが取得できます。
$messages = $validator->messages();
メッセージではなく、バリデーションで失敗したことを示す配列へアクセスすることも可能です。使用するにはfailed
メソッドを使ってくだい。
$failed = $validator->failed();
ファイルのバリデーション
Validator
クラスはファイルに対し、size
、mimes
などのようないくつかのバリデーションルールを提供しています。ファイルをバリデーションする場合は、他のデータと一緒にバリデーターへ渡してください。
バリデーション後のフック
バリデーションには、完了した後に実行するコールバックを追加することもできます。これにより、簡単に他の確認作業を追加したり、メッセージコレクションへエラーメッセージを追加したりさえできます。これを行うには、バリデーションインスタンスに対し、after
メソッドを使用してください。
$validator = Validator::make(...);
$validator->after(function($validator)
{
if ($this->somethingElseIsInvalid())
{
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails())
{
//
}
必要に応じて、多くのafter
コールバックを追加することもできます。
コントローラーバリデーション
もちろん、バリデーションを行うために、毎回手動でValidator
インスタンスを生成し、確認するのは面倒ですよね。心配ご無用、別の方法もあります!ベースのApp\Http\Controllers\Controller
クラスは、LaravelのValidatesRequests
トレイトを使っています。このトレイトは、送られてくるHTTPリクエストをバリデーションするための便利なメソッドを一つ提供しています。ご覧ください。
/**
* 投稿されたブログ投稿を保存する
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique|max:255',
'body' => 'required',
]);
//
}
バリデーションが通れば、コードは通常通り実行されます。しかし、バリデーションに失敗すると、Illuminate\Contracts\Validation\ValidationException
が投げられます。この例外は自動的に補足され、ユーザーが前にアクセスしたURLへのリダイレクトを生成します。バリデーションエラーも自動的に、セッションへフラッシュデータとして保存されます!
もし、やって来たリクエストがAJAXリクエストであれば、リダイレクトは生成されません。代わりに、バリデーションエラーを表すJSONを含んだ、422ステータスコードのHTTPレスポンスがブラウザへ返されます。
つまり、通常の書き方をした同等のコードはこのようになります。
/**
* 投稿されたブログ投稿を保存する
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$v = Validator::make($request->all(), [
'title' => 'required|unique|max:255',
'body' => 'required',
]);
if ($v->fails())
{
return redirect()->back()->withErrors($v->errors());
}
//
}
フラッシュデータとして保存されるエラー形式のカスタマイズ
バリデーションが失敗した時に、フラッシュデーターとして保存されるバリデーションエラーの形式をカスタマイズしたければ、ベースコントローラーのformatValidationErrors
をオーバーライドしてください。Illuminate\Validation\Validator
クラスをファイルの先頭でインポートするのを忘れないでください。
/**
* {@inheritdoc}
*/
protected function formatValidationErrors(Validator $validator)
{
return $validator->errors()->all();
}
フォームリクエストバリデーション
より複雑なバリデーションのシナリオでは、「フォームリクエスト」を生成したほうが良いでしょう。フォームリクエストは、バリデーションロジックを含んだカスタムリクエストクラスです。フォームリクエストクラスを作成するには、make:request
Artisan CLIコマンドを使用します。
php artisan make:request StoreBlogPostRequest
生成されたクラスは、app/Http/Request
ディレクトリーへ設置されます。では、バリデーションルールを少しrules
メソッドへ追加してみましょう。
/**
* リクエストに適用される、バリデーションルールを取得
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique|max:255',
'body' => 'required',
];
}
では、どのようにバリデーションルールを実行するのでしょうか?必要なのは、コントローラーのメソッドで、このリクエストをタイプヒントで指定することです。
/**
* やってきたブログ投稿を保存する。
*
* @param StoreBlogPostRequest $request
* @return Response
*/
public function store(StoreBlogPostRequest $request)
{
// やってきたリクエストは有効だった…
}
渡されたフォームリクエストは、コントローラーメソッドが呼び出される前に確認されます。既に、バリデーション済みです!
バリデーションに失敗すると、前のアドレスにユーザーを戻すために、リダイレクトレスポンスが生成されます。エラーも表示できるように、フラッシュデーターとしてセッションに保存されます。もし、リクエストがAJAXリクエストであれば、バリデーションエラーを表現するJSONを含んだ、422ステータスコードのHTTPレスポンスがユーザーに返されます。
フォームリクエスト権限
フォームリクエストクラスは、authorize
メソッドも用意しています。このメソッドでは、認証されているユーザーが、指定されたリソースを更新する権限を実際に持っているのかを確認します。例えば、ユーザーがブログポストのコメントを更新しようとしているなら、本人のコメントなのでしょうか?調べてみましょう。
/**
* ユーザーがこのリクエストの権限を持っているかを判断する
*
* @return bool
*/
public function authorize()
{
$commentId = $this->route('comment');
return Comment::where('id', $commentId)
->where('user_id', Auth::id())->exists();
}
上の例の中の、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\Validation\Validator
クラスをファイルの先頭でインポートするのを忘れないでください。
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
エラーメッセージの操作
Validator
のインスタンスに対し、messages
メソッドを呼びだせば、エラーメッセージを操作するのに便利な様々なメソッドを持つMessageBag
インスタンスが取得できます。
指定フィールドの最初のエラーメッセージ取得
echo $messages->first('email');
指定フィールドの全エラーメッセージ取得
foreach ($messages->get('email') as $message)
{
//
}
全フィールドの全エラーメッセージ取得
foreach ($messages->all() as $message)
{
//
}
指定フィールドのメッセージ存在確認
if ($messages->has('email'))
{
//
}
エラーメッセージのフォーマットを指定し取得
echo $messages->first('email', '<p>:message</p>');
デフォルトでは、エラーメッセージはBootstrapコンパチブルな形式が使われます。
全エラーメッセージをフォーマット指定し取得
foreach ($messages->all('<li>:message</li>') as $message)
{
//
}
エラーメッセージとビュー
一度バリデーションを実行したら、エラーメッセージをビューで簡単に表示する方法が欲しくなるでしょう。Laravelでは便利に行えます。以下のルートを参考にしてください。
Route::get('register', function()
{
return View::make('user.register');
});
Route::post('register', function()
{
$rules = [...];
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails())
{
return redirect('register')->withErrors($validator);
}
});
バリデーションに失敗した場合、Validator
インスタンスをリダイレクトのwithErrors
メソッドに渡していることに注目してください。このメソッドはセッションにエラーメッセージをフラッシュデーターとして保存し、次のリクエストで使用できるようにします。
しかし、GETルートの中で明示的にエラーメッセージをビューに結合していないことにも注目してください。これは常にLaravelがセッションにerrorsが存在しないかチェックしており、存在時は自動的にビューに結びつけてくれるからです。ですから、$errors
変数はいつでも全リクエスト中の、全ビューで使用でき、あなたは$errors
はいつでも定義済みだと確信し、安心して使用できるのです。$errors
変数はMessageBag
インスタンスです。
ですから、リダイレクトした後に、ビューと自動的に結び付けられた$errors
変数を便利に利用してください。
<?php echo $errors->first('email'); ?>
名前付きエラーBag
一つのページに複数のフォームがある場合、エラーのMessageBag
に名前を付けたいこともあるでしょう。これにより、特定のフォームに対するエラーメッセージを取得できるようになります。withErrors
への第2引数として、名前を渡すだけです。
return redirect('register')->withErrors($validator, 'login');
これで、$errors
変数により、名前付きMessageBag
インスタンスへアクセスできます。
<?php echo $errors->login->first('email'); ?>
用意されているバリデーションルール
以下が使用可能なバリデーションルールとその機能のリストです。
- 受け入れ
- アクティブなURL
- (日付)後
- 英文字
- 英記号
- 英数字
- 配列
- (日付)前
- 範囲
- 論理
- 確認
- 日付
- 日付形式
- 相違
- 桁指定数値
- 桁範囲指定数値
- メールアドレス
- 存在(データベース)
- 画像(ファイル)
- 内包
- 整数
- IPアドレス
- 最大値
- MIMEタイプ
- 最小値
- 非内包
- 数値
- 正規表現
- 必須
- 指定フィールド指定値時必須
- 指定フィールド存在時必須
- 全指定フィールド存在時必須
- 指定フィールド非存在時必須
- 全指定フィールド非存在時必須
- 同一
- サイズ
- 文字列
- タイムゾーン
- 相違(データベース)
- URL
accepted
そのフィールドがyes、on、1、trueであることをバリデートします。これは「サービス利用規約」同意のバリデーションに便利です。
active_url
フィルドがPHPの機能であるcheckdnsrr
を通して、有効なURLであるかをバリデートします。
after:日付
フィールドの値が与えられた日付以降であるかバリデーションします。日付はPHPのstrtotime
関数で処理されます。
alpha
フィールドが全部アルファベット文字であることをバリデートします。
alpha_dash
フィールドが全部アルファベット文字とダッシュ(-)、下線(_)であることをバリデートします。
alpha_num
フィールドが全部アルファベット文字と数字であることをバリデートします。
array
フィールドが配列タイプであることをバリデートします。
before:日付
フィールドが与えられた日付より前であることをバリデートします。日付はPHPのstrtotime
関数で処理されます。
between:最小値,最大値
フィールドが指定された最小値と最大値の間のサイズであることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、ファイルは評価されます。
boolean
フィールドが論理値として有効であることをバリデートします。受け入れられる入力は、true
、false
、1
、0
、"1"
、"0"
です。
confirmed
フィールドがそのフィールド名+_confirmation
フィールドと同じ値であることをバリデートします。例えば、バリデーションするフィールドがpassword
であれば、同じ値のpassword_confirmation
フィールドが入力に存在していなければなりません。
date
パリデーションされる値はPHP関数のstrtotime
を使用し確認されます。
date_format:フォーマット
バリデーションされる値がフォーマット定義と一致するか、PHP関数のdate_parse_from_format
を使用し確認されます。
different:フィールド
フィールドが指定されたフィールドと異なった値を指定されていることをバリデートします。
digits:値
フィールドが数値で、値の桁数であることをバリデートします。
digits_between:最小値,最大値
フィールドが整数で、桁数が最小値から最大値の間であることをバリデートします。
フィールドがメールアドレスとして正しいことをバリデートします。
exists:テーブル,カラム
フィールドの値が、指定されたデータベーステーブルに存在することをバリデートします。
基本的なExistsルールの使用法
'state' => 'exists:states'
カスタムカラム名の指定
'state' => 'exists:states,abbreviation'
さらにクエリーへWHERE節として追加される条件を追加することも可能です。
'email' => 'exists:staff,email,account_id,1'
NULL
を"where"節の値として渡せば、データベースの値がNULL
であることを追加でチェックできます。
'email' => 'exists:staff,email,deleted_at,NULL'
image
フィールドで指定されたファイルが画像(jpg、png、bmp、gif、svg)であることをバリデートします。
in:foo,bar...
フィールドが指定されたリストの中の値に含まれていることをバリデートします。
integer
フィールドが整数値であることをバリデートします。
ip
フィールドがIPアドレスの形式として正しいことをバリデートします。
max:値
フィールドが最大値として指定された値以下であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、ファイルが評価されます。
mimes:foo,bar,...
フィールドで指定されたファイルが拡張子のリストの中のMIMEタイプのどれかと一致することをバリデートします。
mimesルールの基本的な使用法
'photo' => 'mimes:jpeg,bmp,png'
min:値
フィールドが最小値として指定された値以上であることをバリデートします。size
ルールと同様の判定方法で、文字列、数値、ファイルが評価されます。
not_in:foo,bar,...
フィールドが指定されたリストの中の値に含まれていないことをバリデートします。
numeric
フィールドは数値であることをバリデートします。
regex:正規表現
フィールドが指定された正規表現にマッチすることをバリデートします。
注目:
regex
パターンを使用する場合は、ルールをパイプ(縦棒)で区切るのではなく、配列で指定することが必要になります。特に正規表現に縦棒を含んでいる場合は該当します。
required
フィールドに入力データーが存在することをバリデートします。
required_with_all:foo,bar,...
The field under validation must be present if the field is equal to any value.
required_with:foo,bar,...
引数で指定されたフィールドのうち、どれかが存在している場合のみ、フィールドが入力されていることをバリデートします。
required_with_all:foo,bar,...
引数で指定されたフィールドのうち、全てが存在している場合のみ、フィールドが入力されていることをバリデートします。
required_without:foo,bar,...
フィールドは、指定された他のフィールドのうちどれかが存在しない場合のみ、この項目が入力されていることをバリデートします。
required_without_all:foo,bar,...
フィールドは、指定された他のフィールド全部が存在しない場合のみ、この項目が入力されていることをバリデートします。
same:フィールド
フィールドが、指定されたフィールドと同じ値であることをバリデートします。
size:値
フィールドは指定された値と同じサイズであることをバリデートします。文字列の場合、値は文字長です。数値項目の場合、値は整数値です。ファイルの場合、値はキロバイトのサイズです。
string
フィルードは文字列タイプであることをバリデートします。
timezone
timezone_identifiers_list
PHP関数の値に基づき、フィールドがタイムゾーンとして識別されることをバリデートします。
unique:テーブル,カラム,除外ID,IDカラム
フィールドは指定されたデータベースで一意であることをバリデートします。column
オプションが指定されない場合、フィールド名が使用されます。
場合により、バリデーターにより生成されるデータベースクエリーに、カスタム接続を設定する必要があるかもしれません。上記のバリデーションルール、unique:users
ではクエリーに対し、デフォルトデータベース接続が使用されます。これをオーバーライドするには、以下のように行います。
$verifier = App::make('validation.presence');
$verifier->setConnection('connectionName');
$validator = Validator::make($input, [
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users',
]);
$validator->setPresenceVerifier($verifier);
uniqueルールの基本的な使用例
'email' => 'unique:users'
カスタムカラム名の指定
'email' => 'unique:users,email_address'
指定されたIDを無視する
'email' => 'unique:users,email_address,10'
追加のWHERE節を付け加える
さらにクエリーへWHERE節として追加される条件を追加することも可能です。
'email' => 'unique:users,email_address,NULL,id,account_id,1'
上記のルールでは、同一かチェックする対象は、account_id
が1
の行のみになります。
url
フィールドがURLの形式であることをバリデートします。
注目:この機能は、PHPの
filter_var
メソッドを使用しています。
条件付きでルールを追加する
ある状況では、そのフィールドが入力配列の中に存在する場合のみ、バリデーションを実行したいことがあると思います。これを簡単に行うには、sometimes
ルールを追加してください。
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
上の例では、email
フィールドが、$data
配列の中に存在している場合のみ、バリデーションが実行されます。
複雑な条件のバリデーション
時々(sometime)、他のフィールド値が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;
});
注目: クロージャーに渡される
$input
パラメーターは、Illuminate\Support\Fluent
のインスタンスで、フィールドと入力値にアクセスするためのオブジェクトです。
カスタムエラーメッセージ
必要であれば、デフォルトのエラーメッセージの代わりに、カスタムメッセージを使用できます。指定する方法はいくつかあります。
バリデーターへカスタムメッセージ指定
$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' => 'あなたのメールアドレスを教えてもらう必要があります!',
];
言語ファイルでカスタムメッセージ指定
多くの場合、Validator
に直接カスタムメッセージを渡すよりは、言語ファイルに指定したいでしょう。そのためには、resources/lang/xx/validation.php
言語ファイルのcustom
配列にメッセージを追加してください。
'custom' => [
'email' => [
'required' => 'あなたのメールアドレスを教えてもらう必要があります!',
],
],
カスタムバリデーションルール
カスタムバリデーションルールの登録
Laravelは多彩で便利なバリデーションを提供していますが、自分だけの特別なバリデーションを使用したい場合もあるでしょう。カスタムバリデーションルールを登録する一つの方法は、Validator::extend
メソッドを使用する方法です。
Validator::extend('foo', function($attribute, $value, $parameters)
{
return $value == 'foo';
});
カスタムバリデーターのクロージャーは3つの引数を取ります。$attribute
はバリデーションをしているフィールド、$value
はその値、$parameters
はルールに渡された引数です。
クロージャーの代わりにextend
メソッドへクラスとメソッドを渡すこともできます。
Validator::extend('foo', 'FooValidator@validate');
カスタムルールにエラーメッセージも定義する必要があります。同時にエラーメッセージを定義することも、また言語ファイルにエントリーを追加することも可能です。
Validatorクラスの拡張
Validatorにクロージャーのコールバックを追加するより、Validatorクラスそのものを拡張したい場合もあるでしょう。それなら、Illuminate\Validation\Validator
を拡張して自分のValidatorを書くこともできます。そのクラスにvalidate
のプレフィックスをつけたバリデーションメソッドを追加してください。
<?php
class CustomValidator extends Illuminate\Validation\Validator {
public function validateFoo($attribute, $value, $parameters)
{
return $value == 'foo';
}
}
カスタムバリデーターリゾルバーを登録する
次にカスタムバリデーター拡張を登録する必要があります。
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new CustomValidator($translator, $data, $rules, $messages);
});
カスタムバリデーションルールを作成する場合、エラーメッセージ中で置き換えるカスタムプレースホルダーを定義する必要が起きます。今まで説明したカスタムバリデーションの作成を行い、それからバリデーターにreplaceXXX
関数を追加してください。
protected function replaceFoo($message, $attribute, $rule, $parameters)
{
return str_replace(':foo', $parameters[0], $message);
}
Validator
クラスを拡張せずに、カスタムメッセージへ置き換えたい場合は、Validator::replacer
メソッドを使用できます。
Validator::replacer('rule', function($message, $attribute, $rule, $parameters)
{
//
});