CakePHPで同じカラムに複数のカスタムバリデーションをセットする方法

シェアする

CakePHPでユーザ情報をデータベースに登録する機能を実装した時の話です
(CakePHP v3.4.4)。

誕生日を入力するフォームで、入力された日付に対して以下のチェックを行い、入力エラーがある場合はエラー表示をさせること。

  • 2月31日や4月31日など、存在しない日付が入力されていないか
  • 未来の日付が入力されていないか

TableクラスのvalidationDefaultでチェックをさせたい。

しかし、実装してみたところ、片方のバリデーション(後に定義したルール)しか効いていませんでした。

試しにバリデーションの記述の順番を逆にしてみると、同じく片方のバリデーション(後に定義したルール)しか効かない。後に定義したルールしか適応されないのかもしれないと思い込み、つまずきました。

スポンサーリンク

実際に記述したバリデーション(修正前)

birthdayの入力データ($value)は「1982-06-18」(yyyy-mm-dd)
存在する日付かどうかはcheckdate関数を使用しています。
未来の日付かどうかはシステム日付と比較しています。

【UsersTable.php】


    $validator
        ->add(‘birthday’ , [
            ‘date’ => [
                ‘rule’ => function($value) {
                    $year = substr($value,0,4);
                    $month = substr($value,5,2);
                    $day = substr($value,8,2);
                    $flg = checkdate($month,$day,$year);
                    return $flg;
                },
                ‘message’ => ‘無効な日付が入力されています。’
            ],
            ‘date’ => [
                ‘rule’ => function($value) {
                    $today = date(“Y/m/d”);
                    $target = date(“Y/m/d”,strtotime($value));
                    If (strtotime($today) < strtotime($target)) {
                        return false;
                    } else {
                        return true;
                    }
                },
                ‘Message’ => ‘無効な日付が入力されています。’
            ]
        ]);

    …
    …
    …
    return $validator;

わかる方はすぐお気づきかと思いますが、
原因は「ルール名」が被っていること。
上記の‘date’と記載されている部分が、ルール名になります。
それぞれのルール名に「date」と、同じ名前を使用してしまっていますね、、。

これによって「date」のルールは、後に記述した方になってしまいます。
最初のルールの記述は上書きされてしまったということでした、、、、、。

同じカラムに対して複数のカスタムバリデーションを設ける場合、
ルール名はそれぞれ別名で定義しておかなければならないということを知りました。
(そもそもそこがルール名だということを曖昧に理解したまま記述しておりました、、。)

以下のように修正し、被らないようにルール名を設定したところ、
ちゃんとそれぞれのチェックに対してバリデーションの結果が返されました。

修正後のバリデーション

【UsersTable.php】


    $validator
        ->add(‘birthday’ , [
            ‘date_exist’ => [ ←日付の存在チェック用のルール名
                ‘rule’ => function($value) {
                    $year = substr($value,0,4);
                    $month = substr($value,5,2);
                    $day = substr($value,8,2);
                    $flg = checkdate($month,$day,$year);
                    return $flg;
                },
                ‘message’ => ‘無効な日付が入力されています。’
            ],
            ‘date_future’ => [ ←日付が未来かどうかチェック用のルール名
                ‘rule’ => function($value) {
                    $today = date(“Y/m/d”);
                    $target = date(“Y/m/d”,strtotime($value));
                    If (strtotime($today) < strtotime($target)) {
                        return false;
                    } else {
                        return true;
                    }
                },
                ‘Message’ => ‘無効な日付が入力されています。’
            ]
        ]);

    …
    …
    …
    return $validator;

バリデーションの確認

ここでは試しに、未来でかつ存在しない日付「2018-02-31」を入力してみました。
【UsersContoroller.php】


    $data[‘birthday’] = “2018-02-31”;
    $user = $this->Users->patchEntity($user,$data);
    $errors = $user->errors();
    debug($errors);

↓ ↓ ↓


    ‘birthday’ => [
        ‘date_exist’ => ‘無効な日付が入力されています。’,
        ‘date_future’ => ‘無効な日付が入力されています。’
    ]

飲食業界からIT業界に転身してきて現在2年目です。PHPの経験がメインとなります。これまで自分がPHPを扱ってきた上で、モヤモヤしてきたことをメインに記事にしていきますのでよろしくお願いいたします。

スポンサーリンク

シェアする

フォローする