はじめに
2つのフィールドを1つにまとめてバリデーションしたかったけど、
スグにやり方が判らなくてソースを追ってしまったので残しておきます。
前提
- 年月日と時分秒を別々に指定しないとイケないFormをお持ちの画面。
- 期間指定したいので、From - Toでフィールド持ってる
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に書きます(多分)
では~。