【Laravel】バリデーションの種類と使い方

フォームなどからのリクエストの値が正しいかどうかチェックすることをバリデーションと言いますが、Laravelには標準でバリデーション機能が装備されています。その機能のアプローチの仕方がいくつかあるのでまとめてみました。

Laravel6.x以上

標準のvalidateメソッドを使う方法

標準で用意されているメソッドを使う方法です。Controller内で使えて一番手軽で簡単な方法ですが、応用があまり利きません。

例えばブログの投稿などを例にすると以下のようになります。(Laravel公式の記述を抜粋 一部修正)

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * 新ブログポストの保存
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // バリデーション
        $validatedData = $request->validate([
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        // バリデーションが通った後の処理
    }
}

上記のように書くだけでバリデーションが行われます。バリデーションが通らなかった場合は、自動的にリクエスト元のページヘリダイレクトします。同時にエラー内容がフラッシュデータとしてセッションへ保存されます。エラー内容の受け取り方などについては、今回は割愛します。

required、unique:posts、max:255などのバリデーションルールの種類と詳細は、公式をご参照ください。

新しいバリデータインスタンスを作成する方法

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();
        }

        // バリデーションが通った後の処理
    }
}

独自フォームリクエストを使う方法

独自のフォームリクエストクラス作成して、Controllerでリクエストを受け取る前にバリデーションを行います。いろいろ応用が利いたバリデーションをすることができます。

フォームリクエストクラスの作成

以下のコマンドでFormRequestを継承したクラスを作成します。「StoreBlogPost」は任意の名前でOKです。

php artisan make:request StoreBlogPost

コマンドを実行すると、「app/Http/Request」内に新しいフォームリクエストクラスが作成されます。「Request」フォルダがない場合は新規に作成されます。

中身は以下の通り。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreBlogPost 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 [
            //
        ];
    }
}

authorizeメソッド

authorizeメソッドでは、ユーザーがリクエストの権限を持っているかtruefalseで返します。falseを返すと、403ステータスコードを返し、コントローラメソッドは実行されません。例えば以下のように追記します。

public function authorize()
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}

デフォルトではfalseを返しているので、特に判断することがなければ以下のようにtrueを返すように変更します。

public function authorize()
{
    return true;
}

rulesメソッド

バリデーションルールを作成するには、rulesメソッドに以下のように追記します。

public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

他にもオリジナルのFormRequestを上書きできるメソッドがいくつかあります。例えば↓

messageメソッド

エラーメッセージの上書き

public function messages()
{
    return [
        'title.required' => 'タイトルは必須です',
        'body.required' => 'メッセージは必須です',
    ];
}

attributesメソッド

属性の上書き

public function attributes()
{
    return [
        'email' => 'メールアドレス',
    ];
}

prepareForValidationメソッド

バリデーションルールにかける前にリクエスト内容を処理できます。

protected function prepareForValidation()
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

作成したフォームリクエストクラスをControllerで使う

デフォルトでは、「Illuminate\Http\Request」を使うようになっているので、作成したフォームリクエストクラスを使うようにControllerを以下のように変更します。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
//use Illuminate\Http\Request; // 消す
use App\Http\Requests\StoreBlogPost; // 追記

class PostController extends Controller
{
    /**
     * 新ブログポストの保存
     *
     * @param  StoreBlogPost  $request
     * @return Response
     */
    public function store(StoreBlogPost $request) // RequestをStoreBlogPost(独自クラス)に変更
    {
        // 送信されたリクエストは正しい

        // バリデーション済みデータの取得
        $validated = $request->validated();

        // バリデーションが通った後の処理
    }
}

これで、自作したフォームリクエストクラスを使ってバリデーションをすることができたと思います。こちらの方が応用が利くのでおすすめです。