CakePHP でカスタム Validation を追加しやすくする #cakephp

概要

CakePHP には独自に定義したカスタム Validation を使う方法がいくつかある。

Default のバリデーションプロバイダーを差し替えることで、アプリケーション全体で使うようなルールを追加しやすくする。

例えば「会員IDは 0 埋めを含む8桁の数字」のようなカスタムバリデーションを使う場合、下記のような形で呼び出せるようにする。

$validator = new AppValidator();
$validator->memberId('member_id', 'member_id は8桁の数字で指定してください');

Validation を拡張したクラスを作る

Validation を拡張して、カスタム Validation を追加するための独自クラスを作る。

Cake\Validation\Validation を拡張することで、既存のチェック処理を直接的にも間接的にも使える。

class AppValidation extends Validation
{
    /**
     * 会員IDをチェックする
     *
     * @param string $check Value to check
     * @return bool Success
     */
    public static function isMemberId($check)
    {
        // 数字8桁のチェック
        return self::custom($check, '/^\d{8}$/');
    }
}

Validator を拡張したクラスを作る

Validator を拡張して、プロキシメソッドを追加するための独自クラスを作る。

このクラスはなくてもよいのだが、カスタムバリデーションを使う際にいちいち配列を作ったりせずに済むようになるため、よく使うものには用意しておくと便利だと思う。

class AppValidator extends Validator
{
    /**
     * 会員IDのルールを追加する
     *
     * @param string $field The field you want to apply the rule to.
     * @param string|null $message The error message when the rule fails.
     * @return $this
     * @see AppValidation::isMemberId()
     */
    public function memberId($field, $message = null)
    {
        // この辺の書き方は、本家 Validator の類似メソッドを参考にするといいと思う
        $extra = array_filter(['message' => $message]);

        return $this->add(
            $field,
            'member_id',
            $extra + [
                'rule' => 'isMemberId',
            ]
        );
    }
}

デフォルトのバリデーションプロバイダーを差し替える

config/bootstrap.php でバリデーションプロバイダーを差し替えることで、アプリケーション全体に拡張した Validation が適用される。

addDefaultProvider で name を default にすることで、カスタムバリデーションでも provider の明示的な指定が不要になる。

ただし default を差し替える場合、 RulesProvider インスタンスで渡してやる必要がある。

ちなみに name を固有のものにすれば、 プロバイダーを使い分けることが可能。

※その場合、プロバイダーの名前を rule で渡してやる必要がある

// bootstrap.php でデフォルトのプロバイダーを差し替える
Validator::addDefaultProvider(
    'default', 
    new RulesProvider(AppValidation::class)
);

まとめ

  • 独自Validationを作る
  • 独自Validatorを作る
  • 独自Validationをデフォルトのバリデーションプロバイダーにする

上記を行うことで、カスタムバリデーションの追加がしやすくなる。

アプリケーション内横断で使いたいようなカスタムルールはそれなりにあると思うので、同じルールが分散するよりかは、定義する場所を確保しておくとメンテしやすいと思う。

参考