CakePHP 3 のカスタムバリデーションルールは厳密にTRUE/FALSE を返す必要がある

CakePHP 3 のカスタムバリデーションルールは厳密にTRUE/FALSE を返す必要がある

こんにちは、田中です。

最近、Webアプリの開発環境をモダンにするため、CircleCI や Heroku の、業務への導入に挑戦しています。 知見がまとまったらバシャログでご紹介したいと思います。

さて、本日は、CakePHP 3のバリデーションについてちょっとハマったところを紹介します。

デフォルトのバリデーションルールは、 CakePHP3.x では 2.xまでの配列による定義から、validationDefaultメソッドの中で定義する形式に変わりました。(Validating Data — CakePHP Cookbook 3.x documentation

今回、16桁のアラビア数字からなるapp_idというフィールドがあり、厳密にパターンをチェックするため正規表現で 以下のようなバリデーションルールを書きました。

<?php
    public function validationDefault(Validator $validator)
    {
        // ...
        $validator
            ->requirePresence('app_id', 'create')
            ->notEmpty('app_id')
            ->add('app_id', 'appIdFormat', [
                'rule' => function ($value) {
                    return preg_match("/\A[0-9]{16}\z/", $value);
                },
                'message' => 'invalid app id',
            ]);
        // ...

        return $validator;
    }

このルールを検証するため、正しいデータ '1000000000000001' を用意してユニットテストを書きましたが、成功しません。正規表現の記述が間違っているのか、と思いいくつか試行錯誤しましたがダメでした。最後に思い当たったのが、 Validation — CakePHP Cookbook 3.x documentationで、「Custom logic that returns true/false 」と書いてあり、PHP: preg_match の戻り値はInteger型だったということ。もしかしてIntegerじゃダメ?そこで

   return preg_match("/\A[0-9]{16}\z/", $value);
   // ↓↓
   return preg_match("/\A[0-9]{16}\z/", $value) === 1;

と直したら、テストにパスしました。 型を厳密にチェックしていく流れには歓迎したいですが、言語そのものやビルトイン関数の真偽判定との違いには注意が必要なようです。ユニットテストがなかったら潜在バグになっていたかもしれませんね。

Webエンジニア募集中

シーブレインではエンジニアを募集しています。一緒に仕事したい方、是非ご応募ください。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ