在 table 个脏话中搜索单词,所有单词都会被标记

Searching for word in table of profanities, all words get flagged

我的网站上有一个 guestbook/comment 系统的亵渎数据库。 它允许您输入您的姓名、电子邮件、消息和我自己的验证码。其中名称、消息 public 仅显示,并且由于 public,因此审核很重要。

我希望PHP在收到消息时像这样处理消息:

  1. 将消息转换为单词列表。
  2. 遍历数组中的每个单词并执行command/function。该命令应检查当前单词是否在数据库中
  3. 如果它在数据库中 str_replace($bad_word, "[EXPLICIT]", $message) 否则转到下一个单词并重复

到目前为止我有这段代码,其中 $message 是用户消息:

$words_in_msg = explode(' ', $message);

        foreach($words_in_msg as &$word) {
            $res = mysqli_query($con,"
                SELECT * FROM `badwords` WHERE `word` = '".$word."'
            ");
            var_dump($res);
            $num = mysqli_num_rows($res);
            if ($num !== 0) {
                $message = str_replace($word, "[EXPLICIT]", $message);
            }
        }

这段代码大部分都有效,因为它会列出 $message 中的所有单词,并且会连接到数据库。但是在执行 SQL 命令后 出现了问题。我已经尝试使用 var_dump($res) 并得到了结果......但这不是我要找的结果。 This 是我得到的。

我真正需要做的只是简单地替换数据库中的单词。

作为一个子问题,是否有另一种更优化的方式来执行相同的功能?考虑到要扫描超过 1300 个单词,我不确定这是否会太慢。

您在 sql 查询中的连接运算符之间缺少 space,因此不用

SELECT * FROM `badwords` WHERE `word` = '".$word."

您可以使用

SELECT * FROM badwords WHERE word = '". $word ."

我有一些优化技巧:

  1. 使用array_unique限制检查字数:$words_in_msg = array_unique(explode(' ', $message));

  2. 只运行你的查询一次,然后得到所有坏词的数组。因此,将其移出循环。

  3. 在遍历单词数组之前先做一个array_intersect。如果结果数组为空,你可以停在那里,因为没有坏词。

  4. 如果有坏词,你可以使用你当前的循环,而不是 运行每次使用查询:

    foreach($words_in_msg as $word) { 如果( in_array($word, $aryBadWords){ $message = str_replace($word, "[EXPLICIT]", $message); } }

或者,您可以使用单个正则表达式来执行所有替换

$regex = '/(' . implode('|', $words_in_msg) . ')/i';
$message = preg_replace($regex, '[EXPLICIT]', $message);

不运行对每个词进行查询将是一个很大的改进。