为解决框架与DB交互问题,将lumen框架从5.2升级到了5.6
业务中validate验证时,用到了digits_between规则
参数值以35.44为例,在5.2版本里,验证通过,并且能够过滤常见的非法参数
框架升级到5.6之后,提示数据不合法
既然是升级框架引起的问题,那么我们就从validate的digits_between实现着手进行分析:
首先,方法定义的文件发生改变
从5.2的illuminate/validation/Validator.php,5.6搬到了illuminate/validation/Concerns/ValidatesAttributes.php实现(trait)
其次,实现上有微调,区别如图
5.2先检查字段值是否是数值,然后比较字段长度
5.6使用正则匹配数字串(非数字字符取反!preg_match('/[^0-9]/', $value)),然后比较字段长度
可以看出,5.2的digits_between可以匹配小数,升级到5.6之后,只能匹配数字串
进一步分析,作者设计digits_between规则的应用场景
取两组测试数据分析:
假如取值区间定义为10.001~2000.001,期望参数值大于10.001小于2000.001
参数值为1500.1
在5.2中会提示为不合法(validateDigitsBetween的第二个条件不满足,1500.1的字符串长度为6,而下限为10.0001),不符合我们的期望
假如取值区间定义为0.001~5.001,期望参数值大于0.001小于5.001
参数值为1000,在5.2中会通过校验(满足数值,数值字符串长度为4,大于0.001,小于5),显然也不符合我们对于取值区间的定义
当然,两组数据在5.6中都不符合要求(第一个条件就验证不通过)
digits_between从设计之初就不是用来作小数匹配,而是作数字串长度匹配,validateDigitsBetween方法从5.2到5.6的升级,作者修复了参数可以是小数的BUG
我们在业务中使用digits_between来验证数值在小数区间内的方法其实存在疏漏~~~但是在5.2中一直使用digits_between的取值区间上下限值设置的比较特殊,恰好过滤掉了下限值(任何一个数值参数的字符串长度都会大于1>>0.0001),而就业务数据而言,几乎不会出现超过设置的上限值位数(亿)量级参数,直到框架升级,这个方法的实现逻辑改变,这个问题才暴露出来
最后,如何以正确的姿势使用validate验证规则来支持小数区间的匹配呢?
注意到validate还有一条between规则
在validateBetween方法里定义,该方法使用了getSize方法,进一步分析getSize
对于设置了数值类型的匹配规则,并且参数值也是数值,getSize返回参数值本身,可直接用参数值与设置的区间上下限值做比较,因此,小数区间的匹配,定义如下的validate规则即可
"quantity" => 'required|numeric|between:0.0001,999999999.9999'
领取专属 10元无门槛券
私享最新 技术干货