10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CakePHP3Advent Calendar 2016

Day 15

[CakePHP3][Validation]0と自然数のみ許可するValidationのかけ方

Last updated at Posted at 2016-12-14

<編集 2016/12/15 10:21>
昨夜投稿した分ですが、あいてたので。。。
CakePHP3 Advent Calendar 15日目です。
<編集終わり>

小ネタです

CakePHP3 で、数値に自然数というValidation をかけたかったけど、ちょっとハマった。
ついでに、Validationが、内部でどんなことをやってるか見たことがなかったので見てみた。

自然数のValidation

$validator
    ->integer('hoge')
    ->requirePresence('hoge', 'create')
    ->notEmpty('hoge')
    ->naturalNumber('hoge', __('[FATAL] not a natural number.'));

これだけで、自然数のValidation はできる。
つまり、hoge が、 0 以外だったら false になる。

これは簡単だ。
ただ、これを探していた時に見た、
http://api.cakephp.org/3.1/class-Cake.Validation.Validation.html#_naturalNumber
に、

boolean $allowZero optional false
Set true to allow zero, defaults to false

と書いてあった。

盛大に意訳すると、自然数だけでなく、自然数と0 というValidation をかけることもできると書いてある。

なるほど。
それは面白い。

ということで、やってみた。

First Try

$validator
    ->integer('hoge')
    ->requirePresence('hoge', 'create')
    ->notEmpty('hoge')
    ->naturalNumber('hoge', true,  __('[FATAL] not a natural number.'));

だが、うまく動かない。
それどころか、メッセージも表示されない。

困った。

Second Try

$validator
    ->integer('hoge')
    ->requirePresence('hoge', 'create')
    ->notEmpty('hoge')
    ->naturalNumber('hoge', [true],  __('[FATAL] not a natural number.'));

なんとなく、配列にしてみた。
結果は何も変わらない。

ということで、よくわからないから中身を見てみた。
見たのは、
http://api.cakephp.org/3.1/class-Cake.Validation.Validation.html#_naturalNumber

にあるように、Cake\Validation\Validationの中。
(リンクは、Cake\Validation\Validation のAPIについて書かれている)

そして、その中に、ルールが書いてあった。

public static function naturalNumber($check, $allowZero = false)
{
    $regex = $allowZero ? '/^(?:0|[1-9][0-9]*)$/' : '/^[1-9][0-9]*$/';

    return static::_check($check, $regex);
}

なんか、ちゃんと書かれてるっぽい。
なんで動かないんだろう?

ということで、念のため First Try の形に戻して debug してみた。

$validator
    ->integer('hoge')
    ->requirePresence('hoge', 'create')
    ->notEmpty('hoge')
    ->naturalNumber('hoge', [true],  __('[FATAL] not a natural number.'));

public static function naturalNumber($check, $allowZero = false)
{
    debug($check);
    debug($allowZero);
    exit;
    $regex = $allowZero ? '/^(?:0|[1-9][0-9]*)$/' : '/^[1-9][0-9]*$/';

    return static::_check($check, $regex);
}

結果

1
false

ん? __('[FATAL] not a natural number.') すら来てない。

ということで、一度冷静になって考えてみた。
なんでだろう?

そして、ヒントはBake で出てくるコメントに書いてあった。

public function validationDefault(Validator $validator)

これ、見るところ違ったんじゃない?
Validator と 書いてあるではないか。
さっきまで見ていたのはValidation
そもそもメソッドチェーンができるのは、$validatorValidator のインスタンスだからのはず。
これは、何かヒントがあるに違いない!!!
ということで、場所を変更してCake\Validation\Validator を見た。
すると、書いてあるではないか!!!

public function naturalNumber($field, $message = null, $when = null)
{
    $extra = array_filter(['on' => $when, 'message' => $message]);

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

あれ?
これ、ラッパーしてるだけみたい。
しかも、

->naturalNumber('hoge')

の形だと、$allowZeroオプションが強制的に false になるみたい。。。

つまり、そもそも今までやってたやり方では実現できなかったらしい。

ということで正解は、

->add('hoge', 'naturalNumber',
 [
     'rule' => ['naturalNumber', true],
     'message' => '自然数で入力してください'
]);

でした。

それにしても、Validator が中で return $this->add()してるとは思ってなかった。
面白かった。

以上、小ネタでした。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?