记录之前在使用laravel5的验证时踩到的一个坑
现象
1 2 3 4 5
| Validator::make( ['name' => 'Dayle'], ['name' => 'in:Peter, Dayle'] );
|
分析
in的实现
1 2 3 4 5 6 7 8 9 10 11 12 13
| protected function validateIn($attribute, $value, $parameters) { return in_array((string) $value, $parameters); }
protected function parseParameters($rule, $parameter) { if (strtolower($rule) == 'regex') return array($parameter);
return str_getcsv($parameter); }
|
可以看到in的验证就是简单的调用了in_array方法
而参数的获取则是调用了str_getcsv
则原因在于逗号之后的空格导致参数被拆分成了 Peter 和 Dayle (注意Dayle前面有空格)
Dayle前面多了一个空格导致in_array判断失败
异象
回想一下之前的用法
1 2 3 4
| Validator::make( ['id' => '1'], ['id' => 'in:1, 2, 3'] );
|
竟然没问题!?

看起来原因在传入的值为数字还是字符上
测试
为了空格能显示得更清楚, 这边的空格用_代替, 下同
1 2 3 4 5 6 7 8 9
| var_dump(in_array('1', ['1', '2', '3'])); var_dump(in_array('1', ['1_', '2', '3'])); var_dump(in_array('1', ['_1', '2', '3'])); var_dump(in_array(1, ['1', '2', '3'])); var_dump(in_array(1, ['1_', '2', '3'])); var_dump(in_array(1, ['_1', '2', '3'])); var_dump(in_array('a', ['a', 'b', 'c'])); var_dump(in_array('a', ['a_', 'b', 'c'])); var_dump(in_array('a', ['_a', 'b', 'c']));
|
结论
从结果上来看:
- string类型数字可以前置空格
- int类型可以前置/后置空格
- 非数字字符严格匹配
根据PHP的官方文档:
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。
可以解释 2 和 3 的结论
但是
1 2
| var_dump('1'== '_1'); var_dump('1'== '1_');
|

喵喵喵?
说好的转换呢?
反过来对于in的验证
1 2 3 4
| Validator::make( ['id' => '1'], ['id' => 'in:1 ,2 ,3'] );
|
将导致验证失败
所以对于使用laravel的in做验证时, 最好写成
1 2 3 4
| Validator::make( ['id' => '1'], ['id' => 'in:1,2,3'] );
|
#少给自己挖坑#
为自己以前的写法捏把汗