【Laravel】Requestクラスのルールを動的に変える

フォームを実装していると、下記のように選択状況に応じてバリデーションをするかしないか決めたい時があります。

f:id:nakahashi_h:20190724002949p:plain

必須入力の有無であれば、required_ifで対象のinput値を参照して切り替える事が可能です。

readouble.com

しかし、日付データを比較するaftterで現在日時と比較したい場合、使用しないデータだとしてもバリデートされてしまいます。
javascriptで入力値を強制的に消す事も出来ますが、 サーバ側で処理を集約したいと考える人もいらっしゃるのではないでしょうか?

さて、
今回は入力内容を元にバリデーションのルールを動的に切り替える方法について触れます。

実装方法

フォームのバリデーションを実装するときにmake:requestコマンドでRequestクラスファイルを作る方法があります。
このクラスは、Illuminate\Http\Requestクラスを継承しています。

そのため、$this->(input名)で値を取得する事ができます。 

実装例

冒頭の図のようなフォームを例にします。
例えば下記のようなフォームで、delivery_state1(即時)の場合はdateのバリデーションを行わないようにします。

<form method="POST">
    <input type="radio" name="delivery_state" value="1"> 即時に配信する <input>
    <input type="radio" name="delivery_state" value="2"> 配信日時を設定する <input>
    <input type="datetime-local" name="date"></input>
</form>

その場合、対象のRequestクラスで、次のような処理を行います。

<?php
public function rules()
{
    // デフォルトルール
    $defaultRules = [
        'delivery_state' => 'required',
        'date' => 'required_if:delivery_criteria,2|after:"now"'
    ];

    // 即時配信の場合、配信日のバリデーションは行わない
    if($this->delivery_state == 1) {
        unset($defaultRules['date']);
    }
    return $defaultRules;
}

選択された配信方法を確認するために$this->delivery_stateの値を確認して、もし「配信日時を設定する」場合はルールからunset()で除外します。

©︎2017-2018 WebSandBag