2

I have a function which looks something like this...

function filterwords($input='poo poo hello world bum trump'){

    $report_swear = 0;

    $badwords = array('poo','bum','trump');

    $filterCount = sizeof($badwords);

    for($i=0; $i<$filterCount; $i++){
            $input = preg_replace_callback('/\b'.preg_quote($badwords[$i]).'\b/i', function($matches) use ($report_swear) {
                $report_swear++;
                return str_repeat('*', 4);
            }, $input);
    }

    print_r($report_swear);

    return $input;

}

In this example I would expect the $report_swear variable to return 4 but it still returns 0.

Any idea how I alter this within the callback?

Thanks

Tom
  • 12,776
  • 48
  • 145
  • 240

1 Answers1

5

I'm not sure what you are exactly trying to do, but note that you can use the 4th parameter of preg_replace_* that is a counter. Instead of looping on all words you can build a pattern as an alternation (the advantage is that your string is parsed only once, instead of once per word):

function filterwords($input='poo poo hello world bum trump'){
    $badwords = array('poo','bum','trump');
    $badwords = array_map('preg_quote', $badwords);
    $pattern = '/\b(?:' . implode('|', $badwords) . ')\b/i';

    $result = preg_replace($pattern, '****', $input, -1, $count);
    echo $count;
    return $result;
}

If you want to take in account the words length:

function filterwords($input='poo poo hello world bum trump'){
    $badwords = array('poo','bum','trump');
    $badwords = array_map('preg_quote', $badwords);
    $pattern = '/\b(?:' . implode('|', $badwords) . ')\b/i';

    $result = preg_replace_callback($pattern, function ($m) {
        return str_repeat('*', strlen($m[0]));
    }, $input, -1, $count);
    echo $count;
    return $result;
}

Note: if your input string or your list of bad words contains unicode characters, you need to add the u modifier to your pattern and to use mb_strlen in place of strlen. See the php manual for details.

Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
  • For the record, relating to `array_map('preg_quote', $badwords)`, `preg_quote()` does not have `/` as the default delimiter. In other words, if there is a slash in a word, it will not be escaped and will break the pattern. This is a complaint that I have not formally brought to the PHP community. I also find "preg_quote()` to be an unintuitive function name. It should be `preg_escape()` and the function should have a default delimiter of the most common pattern delimiter -- `/`. – mickmackusa Mar 25 '23 at 06:18