Laravelの除外ルールを使いこなす!

こんにちはーむちょこです。

Laravel 6.x系から、バリデーションに特定の条件下ではフィールドを除外するルール「exclude_if」「exclude_unless」が追加されました。

公式の説明がかなりあっさりしていたので、実例を添えてご紹介したいと思います!

公式説明

exclude_if:anotherfield,value

The field under validation will be excluded from the request data returned by the validate and validated methods if the anotherfield field is equal to value.

https://laravel.com/docs/6.x/validation#rule-exclude-if

exclude_if: 他のフィールド, 値

検証中のフィールドは、指定した他のフィールドの値が指定した値と等しい場合、validateメソッドとvalidatedメソッドによって返されるリクエストデータから除外されます。

exclude_unless:anotherfield,value

The field under validation will be excluded from the request data returned by the validate and validated methods unless anotherfield’s field is equal to value.

https://laravel.com/docs/6.x/validation#rule-exclude-unless

exclude_unless: 他フィールド, 値

検証中のフィールドは、指定した他フィールドの値が指定した値と等しくない場合、validateメソッドとvalidatedメソッドによって返されるリクエストデータから除外されます。

活用シーン

たとえばラジオボタンでリクエスト内容が切り替わるような場面で便利です。

例として、ペットの種類で犬を選択したときだけ必須項目が増えるフォームを作ってみました。

猫を選択した場合
犬を選択した場合

実装例

フォームのHTMLコードはこんな感じです。

出力されたHTML
                    <div class="field">
                        <label class="label">ペットの種類はなんですか?<span class="is-danger tag">必須</span></label>
                        <div class="control">
                            <label class="radio">
                                <input  type="radio" name="animal" value="dog" required>&nbsp;犬
                            </label>

                            <label class="radio">
                                <input  type="radio" name="animal" value="cat" id="delegation">&nbsp;猫
                            </label>
                        </div>
                    </div>

                    <div class="field">
                        <label class="label">普段のフード名を教えてください<span class="is-danger tag">必須</span></label>
                        <div class="control">
                            <input
                                class="input " type="text" name="food" value="" required>
                        </div>
                    </div>

                    <div class="field for_dog">
                        <label class="label">ご希望のお散歩コースを教えてください<span class="is-danger tag">必須</span></label>
                        <p class="control">
                            <label class="checkbox">
                                <input type="checkbox" class="checkbox" name="course[]" value="park"> 公園コース
                            </label>
                        </p>
                        <p class="control">
                            <label class="checkbox">
                                <input type="checkbox" class="checkbox" name="course[]" value="river"> 川コース
                            </label>
                        </p>
                        <p class="control">
                            <label class="checkbox">
                                <input type="checkbox" class="checkbox" name="course[]" value="shortest"> 最短コース
                            </label>
                        </p>
                    </div>

まずRequestクラスを生成します。

コマンド
$ php artisan make:request SampleRequest
Request created successfully.

生成されたRequestクラスのrules()メソッドを編集して、まずは選択の結果は関係なく、それぞれの項目のルールを定義しておきます。

app/Http/Requests/SampleRequest.php
use Illuminate\Validation\Rule;

public function rules()
{
    return [
        'animal' => [
            'required',
            Rule::in(['dog', 'cat'])
        ],
        'food' => [
            'required',
            'max:255'
        ],
        'course' => [
            'required'
        ],
        'course.*' => [
            Rule::in(['park', 'river', 'shortest'])
        ]
    ];
}

定義したルールは以下のとおりです。

animal:必須、dogかcatのみを受け付ける
food:必須、255文字以内
course:必須、配列の値はpark, river, shortestのいずれかのみを受け付ける

次に、本題であるexclude_ifやexclude_unlessを使ってanimalの値がdogでないときはcourseを除外するルールを付け足してみます。

exclude_if

まずexclude_ifを使ったパターンです。

app/Http/Requests/SampleRequest.php
'course' => [
    'exclude_if:animal,cat',
    'required'
],

これでanimalの値がcatのときにcourseが除外されるようになります。

courseの値がなんであろうとvalidate()が通り、validated()の返り値からはcourse要素が消えます。

app/Http/Controllers/ProjectController.php
var_dump($request->validated());

array(2) {
  ["animal"]=>
  string(3) "cat"
  ["food"]=>
  string(3) "カナガン"
}

exclude_unless

今度はexclude_unlessを使って実装してみます。

app/Http/Requests/SampleRequest.php
'course' => [
    'exclude_unless:animal,dog',
    'required'
],

animalの値がdogでないときにcourseが除外されるようになりました。

一見exclude_ifと全く同じ条件で実装されているように見えますが、exclude_unlessの場合はanimalの値が空のときもcourseが除外されることにご注意ください。

以上、exclude_ifとexclude_unlessの使い方のご紹介でした!