mb_strstr
Finds the first occurrence of a substring and returns the rest of the string from that point.
mb_strstr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding = null): string|false- Added in PHP 5.2.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$haystack | string | The string to search in. |
$needle | string | The string to find. Since PHP 8.0 an empty needle is allowed and matches at position 0. |
$before_needleoptional | bool= false | When true, returns everything before the needle instead of everything from the needle onwards. |
$encodingoptional | ?string= null | Character encoding of haystack and needle. Falls back to the internal encoding when null. |
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
Throws a ValueError if encoding names an unknown character encoding.
Changelog
- PHP 8.0.0needle now accepts an empty string.
- PHP 8.0.0encoding is nullable now.
mb_strstr() is the encoding-aware version of strstr(). It locates the first occurrence of needle and hands you back a slice of the haystack rather than a position, which makes it convenient for splitting a string on its first delimiter without doing index arithmetic.
When to reach for it
Use it when you want the text on one side of a separator and the separator only appears meaningfully once — a header line, a key=value pair, a filename and its extension. Pass true as the third argument for the left-hand side, leave it out for the right-hand side (which still includes the needle itself).
For UTF-8 specifically strstr() usually behaves identically, because UTF-8 is self-synchronising and a multibyte sequence cannot appear inside another character. The multibyte version earns its keep for stateful or fixed-width encodings such as ISO-2022-JP, UTF-16 or SJIS, where a raw byte search can match a fragment of a character and return corrupted text.
What trips people up
The return value is false on failure but an empty string when the needle is found at position 0 and before_needle is true. Both are falsy, so if (!mb_strstr(...)) cannot tell "not found" from "found at the start". Compare with === false.
Example
When to use it
- Split an HTTP header line into its name and value at the first colon.
- Pull the domain out of an email address by taking everything from the @ onwards.
- Grab the query string from a URL by searching for the first ? character.
- Safely cut a string at a delimiter in SJIS or ISO-2022-JP data where byte-level search is unsafe.
Frequently asked questions
What is the difference between mb_strstr and strstr?
mb_strstr interprets both strings in a character encoding instead of as raw bytes, so it cannot match a partial multibyte character. For UTF-8 the results are almost always identical; the difference matters for stateful or fixed-width encodings such as ISO-2022-JP and UTF-16.
How do I get the text before a character in PHP?
Pass true as the third argument: mb_strstr($string, $needle, true) returns everything from the start of the string up to but not including the needle. It returns false if the needle is not present at all.
Does mb_strstr include the needle in the result?
Yes, by default the returned string starts with the needle. Use mb_substr on the result, or mb_strpos plus mb_substr, if you want the text after the needle without it.
More examples
Split a header into name and value
The first call takes everything before the colon, the second takes everything from the colon onwards and then drops that one character with mb_substr. The final var_dump shows the trap: mb_stristr matches at position 0, so with before_needle it returns string(0) "" — an empty string, not false.
<?php
$header = "Content-Type: text/html; charset=UTF-8";
$name = mb_strstr($header, ":", true);
$value = mb_trim(mb_substr(mb_strstr($header, ":"), 1));
echo "name=$name\n";
echo "value=$value\n";
var_dump(mb_stristr($header, "content-type", true));Case-insensitive and last-occurrence variants
mb_stristr ignores case, so it finds "Datei" and prints from there. mb_strrchr searches from the right and returns the final colon plus the filename. The last line returns false because mb_strstr is case-sensitive and lowercase "datei" never appears.
<?php
$line = "WARN: Datei nicht gefunden: bücher.csv";
echo mb_stristr($line, "datei"), "\n";
echo mb_strrchr($line, ":"), "\n";
var_dump(mb_strstr($line, "datei"));
Discussion