またどこかでCTOっぽいことやってる人のブログ

フリーランスを経て、またどこかでCTOっぽいことをやってる人が書いてます。何か色々やってます。

CakePHP3で入力された複数のカラム同士を比較するバリデーションを作ってみた。

今回のネタは合っているのかどうかよくわかっていません。
やりたかったことは大したことではなく

  • 入力されたFrom日付とTo日付の比較

です。
よくあるアレです。入力されたFrom日付がTo日付より未来日の場合はダメというやつです。
最初はvalidationDefaultをごにょごにょやっていたのですが、どうも上手くできず。
もしかしたらできないのかもしれませんが、その辺調べていません。
ですので、buildRulesの方に実装してみました。

以前書いたように、CakePHP3のバリデーションには2種類あります。
ひとつはPOSTデータを送信する際に処理される「validationDefault」、もうひとつはsaveメソッド実行時に処理される「buildRules」です。
ごにょごにょと触った感じ、validationDefaultの方はPOSTデータのカラムをひとつずつ、何らかのバリデーションを実行しているように思えました。
CakePHP2の頃は入力カラム同士でバリデーションできたような気がするのですが、気のせいだったかもしれません。

前置きはともかく、こんな処理を作って実装しました。
昔の自分が書いたコードを雑に修正しただけなんですが。

<?php
 public function buildRules(RulesChecker $rules) {
        
    // 開始日時と終了日時の入力範囲チェック
    $rules->add(
        function ($entity, $options) {
            if ($entity->to_time < $entity->from_time) {
                return false;
            } else {
                // 未入力の場合はtrueで返す
                return true;
            }
        }, [
            'errorField' => 'start_datetime', 
            'message' => '開始日時に設定された日付が、終了日時より未来日として設定されています。'
        ]
    );

    // 処理結果を返す
    return $rules;
 }

この処理はTableに書いてあるのですが、$entityというのはEntity配下に作成するであろう対象テーブルのエンティティです。
エンティティから比較したいカラムを抜いてきて、それを単純に比較しているだけです。
あとはCakePHP3のバリデーションルールに沿って、明示的にtrue / falseを返す。これだけです。

今回は日付のバリデーションなので、Controller側に直接書いたり入力時点でJavaScriptで判定したりとかでもいいと思います。
なんですが、バリデーションはバリデーションとしてまとまってた方がいいかなと。

これもまた個人的な好みです。