最近运营的同事反映,用户发布的帖子内容很多都进入到了待审核状态
由于我们系统中有一套敏感词检查的机制,如果包含敏感词则帖子进入先审后发
其中就用到了strpos 函数,众所周知,strpos用于查找字符串中某个子串第一次出现的位置。
每次数据来了,想要查找这个字符串中某个字符是否存在,就会使用到它。
但是我们排查发现在某些帖子实际中并没有存在设置的关键词,那这个又是因为什么呢?
排查发现是运营设置了部分纯数字的关键词
分析
假设有一个字符串"I don't happy ! xxxx585xxx",现在需要找到585出现的位置,检查其是否存在该关键词。
理想状态中我们可能认为代码这样抒写即可,当然可能大部分时候也确实是这样写的
$string ='I don\'t happy ! xxxx585xxx'; $numtmp = 585; echo strpos($string,$numtmp);
但是我们在检查结果中却出人意料的出现了错误,其输出结果是0,但我们的期望值是20
这时候就出现了一个结果的误差,虽然检查585的时候是0,会判断字符串中存在这个内容,但如果是检查5则会是false。
原因
那本着寻求本真的精神,原因到底是什么呢?在参考了部分资料之后得出结论
strpos对于非字符串类型的数据使用php_needle_char
做了一次类型转换,强制类型转换。
C 代码,如果是整数类型,则强制转换成char类型。所以当你传入585的时候,使用char进行强转之后得到的结果是字符串"I",所以实际上截取之后的字符串长度为0。
现在就很清晰明了了,因为PHP底层对数值型的参数做了一次强制的转化,使得她本身检查的内容发生了变化,才出现结果的误差
需要注意类型转换分为下列几种情况:
1、整形,长整型直接转成char类型
2、布尔值,分别转成字符'1','0',所以strpost('e1',true);返回内容为1
3、double类型数据,先强转为长整型再转换成char类型
4、对象则对对象id进行char的转换
5、其他类型触发E_WARNING的警告到这里就了解了为什么给一个整数,strpos会有意向不到的结果。
解决方案
既然系统需要字符型数据,那我们则对被检查的数据 提前进行 (string) 处理皆可
//方案1 $string ='I don\'t happy ! xxxx585xxx'; $numtmp = '585'; echo strpos($string, $numtmp); //方案2 $string ='I don\'t happy ! xxxx585xxx'; $numtmp = 585; echo strpos($string, (string)$numtmp);
这样我们就得到了预期的结果~
作者:旧旧的 <393210556@qq.com> 解决问题的方式,就是解决它一次