CakePHP3 で「いずれかの入力が必須」を実現するバリデーション

どれか1つが入力されていたら OK とするようなバリデーションです。 Cookbook にもなくてググっても出ないんですけどみなさんどうしてるんでしょうか。

今回は モデルのないフォーム に実装したので、_buildValidator() に記述していますが、モデルのある通常のフォームであれば validationDefault() に記述すれば大丈夫だと思います。

<?php
namespace App\Form;

use Cake\Form\Form;
use Cake\Utility\Hash;
use Cake\Validation\Validator;

class HogeForm extends Form
    protected function _buildValidator(Validator $validator)
    {
        return $validator
            ->notEmpty('foo', '1つ以上入力してください。', function ($context) {
                return Hash::get($context, 'data.foo') === ''
                    && Hash::get($context, 'data.bar') === ''
                    && Hash::get($context, 'data.baz') === ''
                ;
            })
        ;
    }
}

これで foo bar buz のすべてが未入力の場合のみバリデーションにひっかかるようになります。

肝は notEmpty() の3つ目の引数 $when に関数を渡してるとこです。 Validator の API を見る限り他の関数でも $when には callable を渡すことができて、渡した関数が true を返す場合にそのバリデーションが実施されます。 今回の場合だと foo bar buz のすべてが未入力の場合に notEmpty() のバリデーションが働いてエラーとしてくれます。

$context にはバリデーション関係のデータが配列で格納されているのでいじるときは debug($context) とかして見ながら作ると早いかもです。 View 側のエラー表示はいつものように <?= $this->Form->error('foo') ?> で表示させます。

なんかあんまりスマートじゃない気がするのでモアベターがあれば教えてほしいです。