Laravel 5.7でAPI開発時にFormRequestを使ってバリデーションする方法をご紹介します。
実際に移植した時の話も含めて読みたい場合ははてなブログに書いた記事をご覧ください。
(調べた感じLaravel5.5以降でないと違う書き方になるようです)
FormRequestとは
FormRequestとはリクエストのバリデーションルールを定義するLaravelの仕組みです。
FormRequestをコントローラーメソッドにDIしてあげると、バリデーションが通った時だけコントローラー内の処理が走ります。
これによりコントローラーはリクエストに不正な値が入っている可能性を除外できるため、自分の処理だけに専念できます。
FormRequestを作成する
まずArtisanCLIコマンドのmake:request
を使用して、FormRequestのファイルを作成しましょう。
php artisan make:request LoginRequest
app/Http/Requests
以下にファイルが作成されます。
このファイルにバリデーションを移植します。
まず作成されたファイルはこのようになっています。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
ここで一番気をつけるべきなのはpublic function authorize()
です。
デフォルトでfalse
を返すようになっていますが、特にアクセス権限などを求めないリクエストであればtrue
を返すように書き換えてください。
バリデーションルールを定義
まずバリデーションのルールを定義します。
public function rules()
{
return [
'email' => 'required|string|max:64',
'password' => 'required|string|max:64',
];
}
ルールはこれでOKです。
ですがこのままではバリデーションエラーが発生した時にHTMLを返してしまいますので、JSONを返すようにメソッドをオーバーライドしていきます。
レスポンスを定義
function failedValidation(Validator $validator)
を定義します。
ここではバリデーションを走らせて失敗した後のvalidatorが引数に渡されます。
ですから$validator->errors()
などを駆使してレスポンスのjsonを生成しましょう。
そして戻り値にはHttpResponseException(response)
を返します。
protected function failedValidation(Validator $validator) {
$res = response()->json([
'errors' => $validator->errors(),
], 400);
throw new HttpResponseException($res);
}
afterなどの追加処理を定義
$validator->after()
などの特殊処理を定義する場合はfunction withValidator(Validator $validator)
を定義します。
ここではバリデーションが実行される前に呼び出されるので、validatorを使って何か事前処理を書きたい場合に使います。
public function withValidator(Validator $validator) {
$validator->after(function ($validator) {
if ($this->input('name') === 'terminator') {
$validator->errors()->add('name', 'ログインできません');
}
});
}
完成したFormRequest
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class LoginRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'email' => 'required|string|max:64',
'password' => 'required|string|max:64',
];
}
protected function failedValidation(Validator $validator) {
$res = response()->json([
'errors' => $validator->errors(),
], 400);
throw new HttpResponseException($res);
}
public function withValidator(Validator $validator) {
$validator->after(function ($validator) {
if ($this->input('name') === 'terminator') {
$validator->errors()->add('name', 'ログインできません');
}
});
}
}
FormRequestを組み込む
作成したLoginRequestをコントローラーに組み込んでバリデーションに使用してもらいましょう。
コントローラーメソッドの引数にあったRequest
をLoginRequest
に変更するだけです。
use App\Http\Requests\LoginRequest; // インポートを忘れずに
public function login(LoginRequest $request) {
// request is valid ......
}
まとめ
Controller内のバリデーションをFormRequestに抽出するだけ多くのメリットをもたらします。
何か事情がなければ最初からFormRequestを使った方がいいですね。