mb_strripos
Finds the character position of the last case-insensitive match of a substring in a string.
mb_strripos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|false- Added in PHP 5.2.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$haystack | string | The string to search in. |
$needle | string | The string to search for. May be empty as of PHP 8.0. |
$offsetoptional | int= 0 | Positive values begin the search that many characters into the haystack; negative values stop the search that many characters before the end. |
$encodingoptional | ?string= null | Character encoding. Null uses the internal encoding. |
Return value
int|falseThe character position of the last match, counted from the start of the haystack, or false if the needle is not found.
Errors
Throws a ValueError if offset is greater than the length of haystack, or if encoding is not a valid encoding.
Changelog
- PHP 8.0.0needle now accepts an empty string.
- PHP 8.0.0encoding is nullable now.
mb_strripos() is the case-insensitive sibling of mb_strrpos(): it reports the position of the last match, counted in characters from the start of the string, ignoring case. The case folding is Unicode-aware, so Ü and ü, Σ and σ, and accented Latin pairs all match — something strripos() cannot do, since it only folds ASCII.
When to reach for it
Use it when the last occurrence matters and the input's casing is unreliable: finding the final ID: marker in a log line that may be written Id: or id:, locating the last extension separator in a filename that came from an uppercase-happy system, or trimming everything after the final keyword. As with all the position functions, if you actually want the surrounding text rather than a number, mb_strrichr() saves you the arithmetic.
What trips people up
The offset is asymmetric and unlike the one in mb_stripos(). A positive value starts the search that far into the haystack; a negative value does not start from the end — it stops the search that many characters before the end, hiding matches in the tail. Getting that backwards silently returns the wrong match.
And the return is still a falsy zero on a match at position 0, so compare with !== false.
Example
When to use it
- Find the last case-varying marker in a log line so you can slice off the trailing payload
- Locate the final extension separator in a filename normalised inconsistently for case
- Trim everything after the last occurrence of a keyword regardless of how it was capitalised
Frequently asked questions
What is the difference between mb_strripos and mb_strrpos?
mb_strripos matches case-insensitively with Unicode case folding, mb_strrpos matches exactly. Both return the character position of the last match.
What does a negative offset do in mb_strripos?
It stops the search that many characters before the end of the haystack, so matches in the final section are ignored. This is different from mb_stripos, where a negative offset sets where the search starts.
Why does mb_strripos return a different number than strripos?
mb_strripos counts characters while strripos counts bytes, and strripos only folds ASCII case. On accented or non-Latin text the two disagree on both the position and whether there is a match at all.
More examples
Positive versus negative offset
The plain call finds the x at 5. Starting at 3 still finds 5, because a positive offset only sets where the search begins. The negative offset excludes the last three characters, so the match at 5 is hidden and the one at 3 is returned instead.
<?php
mb_internal_encoding('UTF-8');
$s = 'aXbXcXd';
var_dump(mb_strripos($s, 'x')); // last x
var_dump(mb_strripos($s, 'x', 3)); // start 3 chars in
var_dump(mb_strripos($s, 'x', -3)); // stop 3 chars before the endCase-insensitive extension lookup
Each line prints the lowercased extension: pdf, gz and (none). The !== false guard matters here because the third filename has no dot at all, and a bare truthiness test would also have misread a name that began with a dot.
<?php
mb_internal_encoding('UTF-8');
foreach (['Rapport.PDF', 'año.tar.GZ', 'noextension'] as $f) {
$pos = mb_strripos($f, '.');
echo $f, ' -> ';
echo $pos === false ? "(none)\n" : mb_strtolower(mb_substr($f, $pos + 1)) . "\n";
}
Discussion