バリデーションの話は尽きないです。過去にもいくつか取り上げました。今回もちょっと頭をひねった話です。
入力例
ユーザーの登録の入力画面で、メルマガの購読をするならドロップダウンで1週間に受信したい回数を指定します。上のキャプチャでは見えないけれど、ドロップダウンで1回、2回、3回の選択が出てきます。メルマガの購読のチェックボックスをオフにしたら、javascriptで回数のドロップダウンの選択を無効としてもいいですね。
この画面の入力値のバリデーションとして、以下のようなコントローラのコードとします。
class DemoController extends Controller { public function create(Request $request) { $options = [ 0 => '-- 選択してください --', 1 => '1回', 2 => '2回', 3 => '3回', ]; return view('demo2')->with(compact('options')); } public function store(Request $request) { $validated = $request->mergeIfMissing([ 'subscribe' => 'N', // メルマガ購読がオフだと値が返ってこないので、ここで値を設定 ])->validate([ 'email' => 'required|email', 'subscribe' => 'required|in:Y,N', // メルマガ購読? 'frequency' => 'required_if:subscribe,Y|integer|in:1,2,3', //購読するなら受信回数をチェック ], ['frequency.in' => '選択してください']); dd($validated); } }
登録ボタンを押して実行してみましょう!
メルマガ購読のチェックボックスをオン(subscribe = ‘Y’)にしたら、必ず受信回数の選択が必要となり期待通りのエラーが表示されます。
上のfrequencyのルールでは、
-
required_if:subscribe,Y
は、「メルマガを購読する」(subscribe = ‘Y’)がオンとなり、requiredとなりfrequencyの値(0)があるので正 -
integer
では、値(0)は整数ゆえに正 -
in:1,2,3
では、値(0)は1でも2でも3でもないので誤
となりエラーです。
さて、今度はメルマガ購読をオフ(subscribe = ‘N’)にして、投稿してみます。
「メルマガを購読する」はオフなのに、どうしてこれもエラーとなるのでしょう?
先と違ってrequired_if:subscribe,Y
ではrequiredとなりませんが、その結果は誤でもありません。しかし最後のルールin:1,2,3
では前回と同様に誤となりエラーなります。
その証拠に、今度はメルマガ購読オフで、1回を選択するとエラーとはなりません。
以前習ったbailを使っても同じです。required_if:subscribe,Y
のルールの結果が誤となるわけでないので。
'frequency' => 'bail|required_if:subscribe,Y|integer|in:1,2,3', //購読するなら受信回数をチェック
exclude_if
一体どうすればよいのでしょうか。そこで登場するのが、exclude_if
のルールです。
'frequency' => 'exclude_if:subscribe,N|required_if:subscribe,Y|integer|in:1,2,3', //購読するなら受信回数をチェック
メルマガ購読がオフ(subscribe = ‘N’)なら、exclude_if:subscribe,N
で他のルールは適用されなく、以下のようにエラーとなりません。
nullable
exclude_ifがややこしいと思うなら、これはどうでしょう?
「– 選択してください –」の選択値を0でなくnullとします。
また、frequencyのルールにおいて、exclude_ifの代わりにnullableと追加します。
class DemoController extends Controller { public function create(Request $request) { $options = [ null => '-- 選択してください --', // 0でなくnullです。 1 => '1回', 2 => '2回', 3 => '3回', ]; return view('demo2')->with(compact('options')); } public function store(Request $request) { $validated = $request->mergeIfMissing([ 'subscribe' => 'N', // メルマガ購読がオフだと値が返ってこないので、ここで値を設定 ])->validate([ 'email' => 'required|email', 'subscribe' => 'required|in:Y,N', // メルマガ購読? 'frequency' => 'nullable|required_if:subscribe,Y|integer|in:1,2,3', // nullableが入っています。 ], ['frequency.in' => '選択してください']); if ($validated['subscribe'] === 'N') { $validated['frequency'] = 0; // nullでなく0とする } dd($validated); } }
匿名関数
まだややこしいと思うならこれはどうでしょう? ルールの匿名関数を使用して「メルマガを購読する」がオンのときだけ値の数字のチェックとしました。
class DemoController extends Controller { public function create(Request $request) { $options = [ 0 => '-- 選択してください --', 1 => '1回', 2 => '2回', 3 => '3回', ]; return view('demo2')->with(compact('options')); } public function store(Request $request) { $validated = $request->mergeIfMissing([ 'subscribe' => 'N', ])->validate([ 'email' => 'required|email', 'subscribe' => 'required|in:Y,N', 'frequency' => [ 'required_if:subscribe,Y', 'integer', function($attribute, $value, $fail) { if (request('subscribe') === 'Y') { if (! in_array($value, [1,2,3])) { $fail('選択してください'); } } } ] ]); dd($validated); } }メルマガ購読の申し込みはこちらから。