PHP
CakePHP
正規表現
cakephp3

【PHP】cakePHPバリデーションのalphaNumericが効かないこと

 CakePHPのバリデーションalphaNumeric信じられる?

本来Cake Bookを参考して、問題ないはずなのに、結局英数字チェックが効かなくて、原因調査に時間かかってしまった。

Cake Bookデータバリデーション

 バリデーションのalphaNumericで日本語チェック

cakePHP3では、バリデーションのalphaNumericチェックが効かないことによる調査:

cakePHP
# Cake Bookデータバリデーションのサンプール

/*
* テストデータ1:「78424あ4264910」 テストデータ2:「78424あ426491」
* 現象:
*  テストデータ1:{"length"=[6~12文字です。]}
*  テストデータ2:通ってしまう  
*/ 
$validator = new Validator();
$validator
 ->allowEmpty('user_id')
 ->add('user_id', [
  'alphaNumeric' => ['rule' => 'alphaNumeric', 'message' => '英数字のみです'],
  'length' => ['rule' => ['lengthBetween', 6,12],  'message' => '6~12文字です。']
  ]);

 CakePHPデータバリデーションの中身を見てみよう!

cakePHP
# Validationの中身を見てみよう~

/**
 * Checks that a string contains only integer or letters
 *
 * Returns true if string contains only integer or letters
 *
 * $check can be passed as an array:
 * ['check' => 'valueToCheck'];
 *
 * @param string|array $check Value to check
 * @return bool Success
 */
public static function alphaNumeric($check)
{
    if (empty($check) && $check !== '0') {
        return false;
    }
    return self::_check($check, '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/Du');
}

/**
 * Runs a regular expression match.
 *
 * @param string $check Value to check against the $regex expression
 * @param string $regex Regular expression
 * @return bool Success of match
 */
protected static function _check($check, $regex)
{
    return is_string($regex) && is_scalar($check) && preg_match($regex, $check);
}

 原因は?

さ、この「/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/Du」という意味ですか?
正規表現らしくて、調べたら、標準Unicode属性だそうです。

キャプチャ.PNG

つまり、日本語だと、これらの正規表現が効かなくて、通ってしまいます。
正規表現チェッカーでも同じ現象となります。

正規表現チェッカー

正規表現:/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/Du
文字列:78424あ4264910

 cakePHPのバリデーションを使いたいとしたら

グーグルで既存vendor中のalphaNumeric()を読み込む前に新しいメソッドalphaNumeric()を作ってからruleにセットしてバリデーション処理を行う方法がありますが、もう一つの方法は、ruleを無名関数で新規作成して、その場でバリデーション処理を行うという方法があります。どしても、cakePHPのバリデーションを使いたいとしたら、無名関数でルールを独自に作成しましょう。

cakePHP
# データバリデーションの改修例

/*
* テストデータ1:「78424あ4264910」 テストデータ2:「78424あ426491」
* 現象:
*  テストデータ1:{"alphaNumeric"=[英数字のみです。], "length"=[6~12文字です。]}
*  テストデータ2:{"length"=[6~12文字です。]}
*/ 
$validator = new Validator();
$validator
 ->allowEmpty('user_id')
 ->add('user_id', [
  'alphaNumeric' => [
    'rule' => function ($value, $context) {
       return preg_match('/^[a-zA-Z0-9]+$/', $value) ? true : false;
       },
    'message' => '英数字のみです'
  ],
  'length' => ['rule' => ['lengthBetween', 6,12],  'message' => '6~12文字です。']
 ]);

 結論

グーグル先生に聞いたら、CakePHP2では同じような現象が出てくるのは少なくないでしょう。
CakePHP3ではまだ治っていないようです。
alphaNumericの英数字チェックに気を付けてね!

参考
正規表現デスクトップリファレンス

---I Love PHP (。・ω・。)ノ♡