stristr

Returns the part of a string from the first case-insensitive match of a substring onwards.

Signature
stristr(string $haystack, string $needle, bool $before_needle = false): string|false
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$haystackstringThe string to search in.
$needlestringThe substring to search for.
$before_needleoptionalbool= falseIf true, return the part of haystack before the needle instead of from the needle onwards.

Return value

string|falseThe portion of haystack starting at the first case-insensitive match (or the portion before it when before_needle is true), or false if the needle is not found.

Changelog

  • PHP 8.2.0Case folding no longer depends on the locale; only ASCII case folding is performed and non-ASCII bytes are compared by value.
  • PHP 8.0.0needle may now be an empty string.
  • PHP 8.0.0Passing an int as needle is no longer supported; it was deprecated in 7.3.0.

stristr is the case-insensitive form of strstr. It finds the first match of $needle and returns everything from that point to the end of $haystack, including the matched text. Set $before_needle to true and you get the part in front of the match instead.

Importantly, the returned substring keeps the original casing from the haystack — only the matching is case-insensitive.

When to reach for it

Splitting a string at a marker whose case you cannot rely on: pulling the domain out of an email at @, taking the value after a : in a header line, or grabbing everything after a keyword in a log message. Combining the two calls — once with before_needle true, once false — splits a string into two halves in a readable way.

What trips people up

People still use it as a containment test. if (stristr($h, $n)) is wrong twice over: it does more work than needed, and it returns a falsy value when the match is at the end and the remainder is '0' or an empty string. Use stripos(...) !== false, or str_contains on lowercased strings.

Case folding is ASCII-only since PHP 8.2, so accented characters do not fold. And with $before_needle set, a match at position 0 returns an empty string, not false — check with !== false.

Example

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

When to use it

  • Extract the domain half of an email address by splitting at the @ sign
  • Take everything after the colon in a header line such as Content-Type: text/html
  • Pull the message body out of a log line by splitting at a keyword like ERROR

Frequently asked questions

What is the difference between stristr and strstr?

stristr matches the needle case-insensitively; strstr is case-sensitive. Both return the remainder of the haystack from the match onwards, with the haystack's original casing intact.

What is the difference between stristr and stripos?

stripos returns the integer position of the match, while stristr returns the actual substring from the match onwards. Use stripos when you need an offset or a simple found/not-found test.

How do I get the text before the match with stristr?

Pass true as the third argument: stristr($haystack, $needle, true) returns everything before the first match, excluding the needle itself. A match at position 0 gives an empty string, not false.

More examples

Splitting a header line

One call with before_needle true gives the header name, the other gives the remainder starting at the colon, which substr and ltrim then tidy up. Original casing of the header name is preserved.

Example · php
<?php
$line  = 'X-Request-Id: abc-123';
$name  = stristr($line, ':', true);
$value = ltrim(substr(stristr($line, ':'), 1));
echo "name = $name\n";   // name = X-Request-Id
echo "value = $value\n"; // value = abc-123

Case-insensitive matching, original casing returned

The needle was lowercase but the returned text keeps the uppercase WARNING from the log line, which str_starts_with confirms. A needle that does not appear returns false rather than an empty string.

Example · php
<?php
$log = '2025-01-01 WARNING: disk almost full';
$msg = stristr($log, 'warning');
echo $msg, "\n";              // WARNING: disk almost full
var_dump(str_starts_with($msg, 'WARNING'));
var_dump(stristr($log, 'error'));  // bool(false)

Why it is a poor containment test

The remainder is the string "0", which PHP casts to false, so the boolean cast reports no match even though one exists. Explicit !== false, or stripos, gives the correct answer.

Example · php
<?php
$s = 'value is 0';
var_dump(stristr($s, '0'));            // string(1) "0"
var_dump((bool) stristr($s, '0'));     // bool(false) - wrong!
var_dump(stristr($s, '0') !== false);  // bool(true)
var_dump(stripos($s, '0') !== false);  // bool(true)

Discussion

  • Be the first to comment on this lesson.