strstr

Returns the part of a string from the first occurrence of a substring onward, or the part before it.

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

Parameters

ParameterTypeDescription
$haystackstringThe input string to search in.
$needlestringThe substring to search for. The search is case-sensitive.
$before_needleoptionalbool= falseIf true, returns the part of haystack before the first occurrence of needle, excluding the needle itself.

Return value

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

Errors

Does not throw; it returns false when the needle is not present.

Changelog

  • PHP 8.0.0needle may now be an empty string, which matches at offset 0 and returns the whole haystack.
  • PHP 8.0.0Passing an int as needle is no longer supported; it is treated as a string.
  • PHP 7.3.0Passing an int as needle (interpreted as a character ordinal) was deprecated.

strstr locates the first occurrence of needle inside haystack and returns everything from that point to the end of the string, including the needle. Pass true as the third argument and you get the part before the match instead, with the needle excluded.

When to reach for it

Use it when you want the split rather than the position: pulling the domain off an email address, taking everything after the first colon in a log line, or chopping a query string off a URL. If you only need to know whether the substring is present, str_contains reads better and is faster. If you need a numeric offset to feed into substr, use strpos.

What trips people up

The return type is string|false, and when the needle sits at position 0 and before_needle is true the result is "" — an empty string, which is falsy. Test with !== false, never with a plain if.

The match is case-sensitive. Use stristr for a case-insensitive search, strrchr to search from the right, and mb_strstr when you need encoding-aware behaviour on multibyte text.

Example

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

When to use it

  • Extract the domain part of an email address, or the local part with $before_needle set to true.
  • Strip everything from the '?' onward to get the path portion of a URL.
  • Take the message body of a log line that starts with a fixed 'LEVEL: ' prefix.
  • Cut a trailing '#' comment off a config line before parsing it.

Frequently asked questions

What is the difference between strstr and strpos?

strstr returns the matching part of the string, while strpos returns the integer offset where the match starts. Use strpos when you need a position to pass to substr, and strstr when the substring itself is what you want.

Does strstr include the needle in the result?

Yes by default — the returned string starts with the needle. When you pass true as the third argument, the needle is excluded and you get only the text before it.

Is strstr case-sensitive?

Yes. Use stristr for a case-insensitive search; it takes the same three parameters and returns the same types.

More examples

Splitting a log line on the first colon

The output is 'ERROR' then 'disk quota exceeded: /var/log'. strstr stops at the FIRST colon, so the second colon stays inside the message — that is the difference from explode() with a limit of 2 only in appearance; here ltrim removes the leading ': ' that strstr kept.

Example · php
<?php
$line = 'ERROR: disk quota exceeded: /var/log';

$level   = strstr($line, ':', true);
$message = ltrim(strstr($line, ':'), ': ');

echo $level, "\n";
echo $message, "\n";

Checking the result safely

The first path prints 'page=2' and the second prints 'no query string'. The explicit === false test is what keeps an empty-but-found result from being mistaken for a miss.

Example · php
<?php
$paths = ['/api/users?page=2', '/health'];

foreach ($paths as $path) {
    $query = strstr($path, '?');
    if ($query === false) {
        echo $path, " -> no query string\n";
    } else {
        echo $path, ' -> ', substr($query, 1), "\n";
    }
}

Discussion

  • Be the first to comment on this lesson.