如何检测用户提交评论是否包含数据库中逗号分隔的违禁词
问题描述
我需要检测用户提交的评论是否包含数据库bad_word表中以逗号分隔存储的违禁词。表结构如下:
| id | words |
|---|---|
| 1 | foo bar, fooBar |
| 2 | aaa bbb, ccc ddd |
目前使用的代码仅能处理每行单个违禁词的场景,无法识别逗号分隔的多个词:
$comment = request('comment'); $bad_word_exists = \App\BadWord::whereRaw("LOCATE(words, ?) > 0", [$comment])->exists();
预期检测效果:
| $comment | $bad_word_exists |
|---|---|
| foo | false |
| foo bar 123 | true |
解决方案
方案一:数据库层面正则匹配
将每行的逗号分隔违禁词转换为正则匹配规则,直接在数据库中完成检测:
$comment = request('comment'); $bad_word_exists = \App\BadWord::whereRaw( "REGEXP_REPLACE(words, ', ', '|') REGEXP ?", [$comment] )->exists();
说明:REGEXP_REPLACE(words, ', ', '|')会把foo bar, fooBar这类格式转换成foo bar|fooBar的正则表达式,只要评论包含其中任意一个违禁词,就会返回存在。如果违禁词包含.、*等正则特殊字符,需要提前转义避免匹配异常。
方案二:PHP层面逻辑处理
先从数据库取出所有违禁词并拆分,再在PHP中检测评论是否包含任意违禁词:
$comment = request('comment'); // 取出所有违禁词并拆分为一维数组 $badWords = \App\BadWord::pluck('words') ->flatMap(function ($item) { // 兼容逗号后带空格/不带空格的情况 return preg_split('/,\s*/', $item); }) ->filter(); // 过滤空值 // 检查评论是否包含任意违禁词 $bad_word_exists = $badWords->some(function ($word) use ($comment) { // 如需大小写不敏感,替换为stripos($comment, $word) !== false return str_contains($comment, $word); });
说明:这种方式逻辑更灵活,可扩展空间大,比如添加大小写忽略、违禁词边界匹配(避免foobar被识别为包含foo)等规则;若违禁词数量较多,建议将拆分后的数组缓存起来,减少数据库查询次数。
内容的提问来源于stack exchange,提问作者Wilson
相关产品推荐
相关产品推荐

