考虑:
$a = 'How are you?';
if ($a contains ‘are’)
echo ‘true’;
假设我有上面的代码,编写语句 if ($a contains 'are')
的正确方法是什么?
考虑:
$a = 'How are you?';
if ($a contains ‘are’)
echo ‘true’;
假设我有上面的代码,编写语句 if ($a contains 'are')
的正确方法是什么?
You can use the strpos()
function which is used to find the occurrence of one string inside another one:
$a = 'How are you?';
if (strpos($a, ‘are’) !== false) {
echo ‘true’;
}
Note that the use of !== false
is deliberate (neither != false
nor === true
will return the desired result); strpos()
returns either the offset at which the needle string begins in the haystack string, or the boolean false
if the needle isn't found. Since 0 is a valid offset and 0 is "falsey", we can't use simpler constructs like !strpos($a, 'are')
.
Now with PHP 8 you can do this using str_contains:
if (str_contains('How are you', 'are')) {
echo 'true';
}
Here is a little utility function that is useful in situations like this
// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
</div>
While most of these answers will tell you if a substring appears in your string, that's usually not what you want if you're looking for a particular word, and not a substring.
What's the difference? Substrings can appear within other words:
One way to mitigate this would be to use a regular expression coupled with word boundaries (\b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
This method doesn't have the same false positives noted above, but it does have some edge cases of its own. Word boundaries match on non-word characters (\W
), which are going to be anything that isn't a-z
, A-Z
, 0-9
, or _
. That means digits and underscores are going to be counted as word characters and scenarios like this will fail:
If you want anything more accurate than this, you'll have to start doing English language syntax parsing, and that's a pretty big can of worms (and assumes proper use of syntax, anyway, which isn't always a given).
If you want to avoid the "falsey" and "truthy" problem, you can use substr_count:
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
It's a bit slower than strpos but it avoids the comparison problems.
if (preg_match('/(are)/', $a)) {
echo 'true';
}
In PHP, the best way to verify if a string contains a certain substring, is to use a simple helper function like this:
function contains($haystack, $needle, $caseSensitive = false) {
return $caseSensitive ?
(strpos($haystack, $needle) === FALSE ? FALSE : TRUE):
(stripos($haystack, $needle) === FALSE ? FALSE : TRUE);
}
strpos
finds the position of the first occurrence of a case-sensitive substring in a string.stripos
finds the position of the first occurrence of a case-insensitive substring in a string.myFunction($haystack, $needle) === FALSE ? FALSE : TRUE
ensures that myFunction
always returns a boolean and fixes unexpected behavior when the index of the substring is 0.$caseSensitive ? A : B
selects either strpos
or stripos
to do the work, depending on the value of $caseSensitive
.var_dump(contains('bare','are')); // Outputs: bool(true)
var_dump(contains('stare', 'are')); // Outputs: bool(true)
var_dump(contains('stare', 'Are')); // Outputs: bool(true)
var_dump(contains('stare', 'Are', true)); // Outputs: bool(false)
var_dump(contains('hair', 'are')); // Outputs: bool(false)
var_dump(contains('aren\'t', 'are')); // Outputs: bool(true)
var_dump(contains('Aren\'t', 'are')); // Outputs: bool(true)
var_dump(contains('Aren\'t', 'are', true)); // Outputs: bool(false)
var_dump(contains('aren\'t', 'Are')); // Outputs: bool(true)
var_dump(contains('aren\'t', 'Are', true)); // Outputs: bool(false)
var_dump(contains('broad', 'are')); // Outputs: bool(false)
var_dump(contains('border', 'are')); // Outputs: bool(false)
</div>
Lot of answers that use substr_count
checks if the result is >0
. But since the if
statement considers zero the same as false, you can avoid that check and write directly:
if (substr_count($a, 'are')) {
To check if not present, add the !
operator:
if (!substr_count($a, 'are')) {
</div>
I had some trouble with this, and finally I chose to create my own solution. Without using regular expression engine:
function contains($text, $word) { $found = false; $spaceArray = explode(' ', $text);
$nonBreakingSpaceArray = explode(chr(160), $text); if (in_array($word, $spaceArray) || in_array($word, $nonBreakingSpaceArray) ) { $found = true; } return $found;
}
You may notice that the previous solutions are not an answer for the word being used as a prefix for another. In order to use your example:
$a = 'How are you?';
$b = "a skirt that flares from the waist";
$c = "are";
With the samples above, both $a
and $b
contains $c
, but you may want your function to tell you that only $a
contains $c
.