strrpos
Finds the position of the last occurrence of a substring in a string.
strrpos(string $haystack, string $needle, int $offset = 0): int|false- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$haystack | string | The string to search in. |
$needle | string | The substring to search for. |
$offsetoptional | int= 0 | If zero or positive, the search is performed right to left but ignores everything before the offset. If negative, the search starts offset bytes from the end and stops there, ignoring everything after it. |
Return value
int|falseThe position where the needle exists relative to the beginning of the haystack string (independent of offset), or false if the needle was not found.
Errors
Throws a ValueError if offset is greater than the length of haystack.
Changelog
- PHP 8.0.0needle now accepts an empty string.
- PHP 8.0.0Passing an int as needle is no longer supported.
strrpos() returns the zero-based byte offset of the last occurrence of needle inside haystack, or false when it is not present. It is case sensitive and binary safe.
When to reach for it
Use it whenever the interesting delimiter is the final one: separating a directory from a filename, splitting a full name at the last space, taking everything after the last dot in a dotted key, or trimming a string at the last space before a length limit. Unlike strrchr(), the needle may be several bytes long, so multi-character delimiters such as '::' or '->' work.
What trips people up
The false/0 confusion applies here too: a needle found at the very first byte returns 0. Compare with !== false, never with ! or ==.
The offset argument is not symmetric. A zero or positive value restricts the search to the part of the string at or after that byte. A negative value makes the search stop that many bytes from the end, so the match must lie before that point. In both cases the value returned is still counted from the start of the string. Passing an offset larger than the haystack throws a ValueError rather than returning false.
Positions are byte offsets, which is what substr() expects but not what a user counting characters would say. Use mb_strrpos() for character positions.
Example
When to use it
- Split a path into a directory and a filename at the last slash.
- Separate a full name into given names and surname at the last space.
- Trim a long string at the last space before a character limit so words are not cut in half.
Frequently asked questions
What is the difference between strpos and strrpos?
strpos returns the position of the first occurrence, strrpos the position of the last. Both count bytes from the beginning of the string and both return false when the needle is absent.
Why does strrpos return false when I pass an offset?
A positive offset restricts the search to the part of the string at or after that byte, so any earlier match is excluded. Use a negative offset if you meant to search only the earlier part of the string.
Is strrpos case sensitive?
Yes. Use strripos() for a case-insensitive search from the end of the string.
More examples
Splitting at the last space
The last space sits at byte 14, so the output is "Ada Byron King" and "Lovelace". The === false branch matters: a mononym like "Prince" has no space, and calling substr() with false as the offset would silently produce the whole string.
<?php
$full = 'Ada Byron King Lovelace';
$i = strrpos($full, ' ');
if ($i === false) {
echo "single name: $full\n";
} else {
echo 'given names: ', substr($full, 0, $i), PHP_EOL;
echo 'surname: ', substr($full, $i + 1), PHP_EOL;
}Offsets and the ValueError
With offset 3 the search window is "lo", so the l at position 3 is the last match; with offset 4 the window is just "o" and nothing is found. An offset past the end of the string is an error rather than a miss, which is why an unvalidated offset from user input needs a try/catch or a range check.
<?php
$s = 'hello';
var_dump(strrpos($s, 'l', 3)); // int(3) — only bytes 3..4 are searched
var_dump(strrpos($s, 'l', 4)); // bool(false) — only 'o' is left
try {
strrpos($s, 'l', 99);
} catch (ValueError $e) {
echo 'ValueError: ', $e->getMessage(), PHP_EOL;
}
Discussion