PHP 8.0 : str_contains()
02, May 2020

No matter what type of project you are in, you would need to check if a substring exists in a string at some point. PHP has loads of helper functions to deal with strings. But till now, there was no direct function to check existance of a substring in another string.

Currently, We rely on strpos() to do it (strstr() can be used too)

$string = 'Twinkle Twinkle Little Star';
$substring = 'Star';

if(strpos($string, $substring) !== false){
   // Substring exists in string

Even though this approach works, it has some drawback.

  • Its little bit ambiguous about what strpos actually doing.
  • Can easily introduce some bug by wrong use of either !== or false

Meet str_contains()

PHP 8.0 brings us simple but useful function str_contains()

str_contains takes a $haystack and a $needle as arguments, checks if $needle is found in $haystack and returns a boolean value (true/false) whether or not the $needle was found. - RFC
$haystack = 'Twinkle Twinkle Little Star';
$needle = 'Star';

if(str_contains($haystack, $needle)){
   // needle exists in haystack

Please note that, if you have empty string ("") in your $needle, str_contains will always return true.

As of PHP 8, behavior of "" in string search functions is well defined, and we consider "" to occur at every position in the string, including one past the end. As such, both of these will (or at least should) return true. The empty string is contained in every string. - Nikita Popov
str_contains("text string", "");  // true
str_contains("", "");     // true
str_contains("", "abc");     // false


  • There is no multi-byte variant of this function because str_contains works on multi-byte string as well.
  • Case-insensitive variant of this function has been left for future implementation as the current author wanted to start small. Which I agree with. Implementing case-insensitive str_contains will require some more touch with multi-byte one and it will make current implementation more complex. If you need to check if substring exists in a string case-insensitive way, you need to fall back to stripos()