<編集 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
。
そもそもメソッドチェーンができるのは、$validator
が Validator
のインスタンスだからのはず。
これは、何かヒントがあるに違いない!!!
ということで、場所を変更して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()
してるとは思ってなかった。
面白かった。
以上、小ネタでした。