😎

Laravel Validation で、2つの項目の内どちらか1つは必須。でも2つ共の入力はダメ、を実現してみる。

2023/04/10に公開

前置き

という事で、タイトルに書いたバリデーションの内容を見て行きたいと思います。
どなたかの名言を借りて表現すれば、「俺か、俺以外か。」のバリデーションって事ですね。

本題

さて、それでは次のようなシチュエーションを考えてみたいと思います。
名前かニックネームか、どちらか片方は必須で、両方共に入力してはいけないという状況です。 (やや非現実的なサンプルですが、そこは気にしないでください)

結論から言ってしまうと、Laravel Ver.9.49 以降であれば、以下のように書くことができます。

    public function rules(): array
    {
        return [
            'name' => ['required_without:nickname', 'nullable', 'string', 'max:100'],
            'nickname' => ['prohibits:name', 'nullable', 'string', 'max:100'],
        ];
    }

    public function messages(): array
    {
        return [
            'name.required_without' => '名前かニックネームは、どちらかは必須です。',
            'nickname.prohibits' => '名前かニックネーム、どちらかだけを入力して下さい。',
        ];
    }

required_without:nickname は、ニックネームに入力が無ければ、名前は必須。
prohibits:name では、ニックネームに入力があれば、名前の入力を禁じるというルールです。
これでひとまずオッケーですね。

という事で以上ではあるのですが、ここで終わるのであれば、わざわざブログ記事にもせず、Twitter で呟いて終わっていた所ですが、例によって少し続きがあります 🍺

続き

prohibits は、Laravel Ver.8.58 から存在しているのですが、Laravel 9.49 未満の場合は、上記は期待した動作にはならないかも知れません。
そもそも prohibit 系のルールには、他にも prohibited, prohibited_if, prohibited_unless などがあるのですが、何気に Laravel 9.49 で挙動が整理されました。
それ未満の場合、'prohibits:name' とした場合、空であるのはもちろん、名前欄が存在する事自体がNGになります。要は、もっと厳しいんですね。
ですが、Laravel 9.49 では、厳しい版の missing 系のルールが登場したので、prohibit 系は、ちょっと緩い系に統一されることになったんですね。

詳しくは、下記などをご覧下さい。
https://github.com/laravel/framework/pull/45716
https://github.com/laravel/framework/pull/45723

上記は、Laravel 10 からの変更では無く Laravel 9.49 からの変更です。Laravel 9.49 って、Laravel 10 のリリースも近い頃なんですが、そこを敢えてマイナーリリースでやっちゃう所が、 Laravel 的ですね😎

それではまた。

Discussion