I'm not a big fan of the "iterate every character" answer from Jigar because it doesn't provide a quick exit when there are no more needles found (it iterates the entire string regardless) -- this can become more costly in longer strings. Imagine you have a 10,000 character string and the only occurrence of the needle is on the first character -- this would mean doing 9999 more iterated checks for no usable output. The truth is I didn't do any benchmarking, it may not be a big deal at all.
As for your method, you merely need to perform a strict comparison on the result of strpos()
so that php will correctly differentiate between a false
and a 0
result. To accomplish this, you only need to wrap your strpos()
declaration in parentheses and write a type-specific comparision (!==false
).
Here are two other ways (a non-regex and a regex):
Code: (Demo)
$string='orem ipsum dolor sit amet, consectetur adipisicing elit.';
$find='o';
$offset=0;
$length=strlen($find);
while(($string_pos=strpos($string,$find,$offset))!==false){ // just use a strict comparison
echo "String $find found at position $string_pos\n";
$offset=$length+$string_pos;
}
echo "\n";
var_export(preg_match_all('/o/',$string,$out,PREG_OFFSET_CAPTURE)?array_column($out[0],1):'no matches');
Output:
String o found at position 0
String o found at position 12
String o found at position 14
String o found at position 28
array (
0 => 0,
1 => 12,
2 => 14,
3 => 28,
)
For your case, preg_match_all()
all is overkill. However, if you want to count multiple different words, or whole words, or something otherwise tricky it may be the right tool.
Beyond this, depending on the searching scenario, str_word_count() has a setting where it can return the offsets of all words in a string -- then you could call a filtering function to only retain your desired word(s). Just thought I'd throw this suggestion in for future readers; it doesn't apply for this question.