'Check if a string contain multiple specific words

How to check, if a string contain multiple specific words?

I can check single words using following code:

$data = "text text text text text text text bad text text naughty";
if (strpos($data, 'bad') !== false) {
    echo 'true';
}

But, I want to add more words to check. Something like this:

$data = "text text text text text text text bad text text naughty";
if (strpos($data, 'bad || naughty') !== false) {
    echo 'true';
}

(if any of these words is found then it should return true)

But, above code does not work correctly. Any idea, what I'm doing wrong?

php


Solution 1:[1]

For this, you will need Regular Expressions and the preg_match function.

Something like:

if(preg_match('(bad|naughty)', $data) === 1) { } 

The reason your attempt didn't work

Regular Expressions are parsed by the PHP regex engine. The problem with your syntax is that you used the || operator. This is not a regex operator, so it is counted as part of the string.

As correctly stated above, if it's counted as part of the string you're looking to match: 'bad || naughty' as a string, rather than an expression!

Solution 2:[2]

You can't do something like this:

if (strpos($data, 'bad || naughty') !== false) {

instead, you can use regex:

if(preg_match("/(bad|naughty|other)/i", $data)){
 //one of these string found
}

Solution 3:[3]

strpos does search the exact string you pass as second parameter. If you want to check for multiple words you have to resort to different tools

regular expressions

if(preg_match("/\b(bad|naughty)\b/", $data)){
    echo "Found";
}

(preg_match return 1 if there is a match in the string, 0 otherwise).

multiple str_pos calls

if (strpos($data, 'bad')!==false or strpos($data, 'naughty')!== false) {
    echo "Found";
}

explode

if (count(array_intersect(explode(' ', $data),array('bad','naugthy')))) {
    echo "Found";
}

The preferred solution, to me, should be the first. It is clear, maybe not so efficient due to the regex use but it does not report false positives and, for example, it will not trigger the echo if the string contains the word badmington

The regular expression can become a burden to create if it a lot of words (nothing you cannot solve with a line of php though $regex = '/\b('.join('|', $badWords).')\b/';

The second one is straight forward but can't differentiate bad from badmington.

The third split the string in words if they are separated by a space, a tab char will ruins your results.

Solution 4:[4]

if(preg_match('[bad|naughty]', $data) === true) { }

The above is not quite correct.

"preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred."

So it should be just:

if(preg_match('[bad|naughty]', $data)) { }

Solution 5:[5]

substr_count()

I want to add one more way doing it with substr_count() (above all other answers):

if (substr_count($data, 'bad') || substr_count($data, 'naughty')){
    echo "Found";
}

substr_count() is counting for how many times the string appears, so when it's 0 then you know that it was not found. I would say this way is more readable than using str_pos() (which was mentioned in one of the answers) :

if (strpos($data, 'bad')!==false || strpos($data, 'naughty')!== false) {
    echo "Found";
}

Solution 6:[6]

You have to strpos each word. Now you are checking if there is a string that states

'bad || naughty'

which doesn't exist.

Solution 7:[7]

A simple solution using an array for the words to be tested and the array_reduce() function:

$words_in_data = array_reduce( array( 'bad', 'naughty' ), function ( $carry, $check ) use ( $data ) {
    return ! $carry ? false !== strpos( $data, $check ) : $carry;
} );

Then you can simply use:

if( $words_in_data ){
    echo 'true';
}

Solution 8:[8]

Here is a function that can perform this operation without using regular expressions which could be slower. Instead of passing a single string for the task, pass an array like

if (strposMultiple($data, ['bad', 'naughty']) !== false) {
    //...
}

Here is the function:

function strposMultiple($haystack, $needle, $offset = 0) {
    if(is_string($needle))
        return strpos($haystack, $needle, $offset);
    else {
        $min = false;
        foreach($needle as $n) {
            $pos = strpos($haystack, $n, $offset);

            if($min === false || $pos < $min) {
                $min = $pos;
            }
        }

        return $min;
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 magento4u_com
Solution 5 candle
Solution 6 Jaakko Kaski
Solution 7 Pablo S G Pacheco
Solution 8 Cem Kalyoncu