LoginSignup
13
12

More than 5 years have passed since last update.

フォームリクエストバリデーションで複数のフィールドを1つにまとめてバリデーションする方法

Last updated at Posted at 2018-07-05

はじめに

2つのフィールドを1つにまとめてバリデーションしたかったけど、
スグにやり方が判らなくてソースを追ってしまったので残しておきます。

前提

  • 年月日と時分秒を別々に指定しないとイケないFormをお持ちの画面。
  • 期間指定したいので、From - Toでフィールド持ってる

こういうヤツ
image.png

postされてくるデータは一応以下みたいな感じで説明

入力欄 key
開始日 start_date 年月日
開始時刻 start_time 時分秒
終了日 end_date 年月日
終了時刻 end_time 時分秒

愚直にやるとどうなるか

コード書くの怠いので、文字で流れを書いてしまうと・・・

  • start_dateのフォーマットチェック
  • start_timeのフォーマットチェック
  • end_dateのフォーマットチェック
  • end_timeのフォーマットチェック

かつ、バリエーション終わった後か、withValidator的なヤツで、

  • start_dateとstart_timeをくっつけてCarbonか何かの日付系インスタンス取得
  • end_dateとend_timeをくっつけてCarbonか何かの日付系インスタンス取得
  • 取得した日付系のインスタンスを比較

怠い&冗長。
あと多分_dateと_timeをくっつけた後でフォーマットチェックもしないとイケない気がする。
(withValidatorってvalidationがfailすると呼ばれないっけ?なら不要)

ソリューション

Illuminate\Foundation\Http\FormRequest::validationDataメソッドを上書きする


/**
 * @inheritdoc
 */
protected function validationData()
{
    $this->addStartAt();
    $this->addEndAt();
    return parent::validationData();
}

/**
 * start_dateとstart_timeからstart_atを作ってリクエストパラメータに追加する
 */
private function addStartAt()
{
    $start_date = (string)$this->request->get('start_date');
    if ($start_date === '') {
        return;
    }
    $start_time = (string)$this->request->get('start_time');
    if ($start_time === '') {
        $start_time = '00:00:00';
    }
    $start_at = $start_date . ' ' . $start_time;
    $this->request->add(['start_at' => $start_at]);
}

/**
 * end_dateとend_timeからend_atを作ってリクエストパラメータに追加する
 */
private function addEndAt()
{
    $end_date = (string)$this->request->get('end_date');
    if ($end_date === '') {
        return;
    }
    $end_time = (string)$this->request->get('end_time');
    if ($end_time === '') {
        $end_time = '23:59:59';
    }
    $end_at = $end_date . ' ' . $end_time;
    $this->request->add(['end_at' => $end_at]);
}

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{
    return [
            'start_at' => [
                'nullable',
                'date',
                'before_or_equal:end_at'
            ],
            'end_at' => [
                'nullable',
                'date',
                'after_or_equal:start_at'
            ],
        ];
}

validationDataはバリデーションされる前に呼ばれるメソッドなので、
これをオーバーライドして任意のパラメータをrequestパラメータに追加する。

フォームリクエストバリデーションなら、
$this->request->add()で任意のパラメータを増やせるので、バリデーション前に足す・・・ならギリありという判断。

パラメータは文字列で渡すので、dateフォーマットになってるか?とかバリエーション任せにできるし、
from - toの並びが正しいかもLaravel任せにできるのでコードもスッキリ。

これで_date、_timeのチェック不要になる。
ただ、_date、_timeでフォーマットが厳格に決まっている場合は、
それぞれちゃんとチェックして入力エラーがあれば画面上で判るようにしといてあげる、程度の配慮は必要です。

さいごに

複数フィールドに対するバリデーションの仕方(required_ifとか使う方法)は割とよく出てるけど、
複数フィールドを合体させて1つのフィールドとしてバリデーションする方法は、情報がないので書いてみました。

最近コードが載らない記事は全部はてなに書いてるので久しぶりにQiitaに投稿してみましたが、
何かプレビューモードが見やすくなったような・・・気のせいかも。

また、コードが載るものを書くときはQiitaに書きます(多分)

では~。

13
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12