str_contains

Checks whether a string contains a given substring, case-sensitively.

Signature
str_contains(string $haystack, string $needle): bool
  • Added in PHP 8.0

Parameters

ParameterTypeDescription
$haystackstringThe string to search in.
$needlestringThe substring to search for.

Return value

booltrue if needle occurs anywhere in haystack, false otherwise.

Errors

Throws a TypeError if a non-string is passed under strict_types; otherwise no errors are raised.

str_contains answers the one question people actually ask of strpos: is this text in there? It returns a plain boolean, so it reads naturally in a condition and removes an entire class of bugs.

When to reach for it

Use it any time you only need presence, not position: checking a Content-Type header for json, filtering a list of filenames, testing whether a message body mentions a keyword, or short-circuiting before a more expensive parse. If you need to know where the match is, or want to slice around it, strpos and strstr are still the right tools.

What trips people up

It is byte-based and case-sensitive. str_contains('Hello', 'hello') is false; lowercase both sides, or use stripos($h, $n) !== false, for a case-insensitive check. An empty needle always returns true, because every string contains the empty string — guard against empty user input before searching or a blank search box will match everything. Being byte-based, it is safe for UTF-8 substring checks (a valid UTF-8 needle can only match at a character boundary), but it knows nothing about Unicode case folding or accent normalisation.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Filter a list of filenames down to those containing a keyword
  • Check a Content-Type header for "json" before decoding a body
  • Detect a banned word in user-submitted text
  • Skip log lines that do not mention a given request ID

Frequently asked questions

What is the difference between str_contains and strpos?

str_contains returns a boolean, strpos returns the byte offset of the match or false. Use str_contains when you only care whether the substring is present; the strpos form needs an explicit !== false comparison because offset 0 is falsy.

Is str_contains case-sensitive?

Yes. Lowercase both strings first, or use stripos($haystack, $needle) !== false, for a case-insensitive check.

Does str_contains work with UTF-8 strings?

Yes for substring checks. It compares bytes, and a valid UTF-8 needle can only match on a character boundary, so results are correct. It does not handle Unicode case folding or accent normalisation.

More examples

Case-insensitive containment

The first check is false because str_contains compares bytes exactly. Lowercasing both operands, or falling back to stripos, both report true. The stripos form avoids allocating two lowercased copies, which matters inside a loop over many rows.

Example · php
<?php
$subject = 'Order CANCELLED by customer';
$needle = 'cancelled';

var_dump(str_contains($subject, $needle));
var_dump(str_contains(strtolower($subject), strtolower($needle)));
var_dump(stripos($subject, $needle) !== false);

Guarding an empty search term

The guarded search returns nothing for an empty term, while the unguarded filter on the last line returns every row — that is the empty-needle rule biting. It is the reason a blank search box can appear to match the whole table.

Example · php
<?php
$rows = ['alpha', 'beta', 'gamma'];

function search(array $rows, string $term): array {
    if ($term === '') {
        return [];
    }
    return array_values(array_filter($rows, fn ($r) => str_contains($r, $term)));
}

print_r(search($rows, 'a'));
print_r(search($rows, ''));
print_r(array_filter($rows, fn ($r) => str_contains($r, '')));

Discussion

  • Be the first to comment on this lesson.