strripos

Finds the position of the last occurrence of a substring, ignoring letter case.

Signature
strripos(string $haystack, string $needle, int $offset = 0): int|false
  • Added in PHP 5.0

Parameters

ParameterTypeDescription
$haystackstringThe string to search in.
$needlestringThe substring to search for.
$offsetoptionalint= 0If zero or positive, the search is performed left to right skipping the first offset bytes of the haystack. If negative, the search starts offset bytes from the end and searches right to left.

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.2.0Case folding no longer depends on the locale set with setlocale(). Only ASCII case folding is done; non-ASCII bytes are compared by byte value.
  • PHP 8.0.0needle now accepts an empty string.
  • PHP 8.0.0Passing an int as needle is no longer supported.

strripos() returns the zero-based byte offset of the last occurrence of needle in haystack, ignoring ASCII letter case, or false if it never occurs. Think of it as strrpos() plus case folding, or stripos() searching from the other end.

When to reach for it

It fits any "last one wins" lookup where the data's capitalisation is inconsistent: the final ERROR/Error/error marker in a log, the last occurrence of a delimiter word in user-entered text, a case-insensitive extension check on a filename that contains several dots.

What trips people up

Like strpos(), a match at position 0 is falsy. Always test with !== false.

The offset argument has two different meanings. A zero or positive value skips that many bytes from the start and then finds the last match in what remains. A negative value makes the search stop that many bytes from the end. Either way, the returned position is measured from the beginning of the whole string. An offset longer than the haystack throws a ValueError.

Since PHP 8.2 case folding is ASCII-only and no longer follows setlocale(), so É and é are not equal. Use mb_strtolower() on both strings, or an mb_ search, for real multibyte matching.

Example

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

When to use it

  • Find the last error marker in a log file whose entries capitalise the word inconsistently.
  • Check a filename for a .PDF or .pdf extension when several dots are present.
  • Locate the final occurrence of a keyword in user-entered text before truncating it.

Frequently asked questions

What is the difference between strripos and strrpos?

They are identical except that strripos ignores ASCII letter case. Both return the position of the last match, or false.

What is the difference between stripos and strripos?

stripos returns the first case-insensitive match; strripos returns the last one. Both count bytes from the start of the string.

Why does a negative offset behave differently from a positive one?

A positive offset skips that many bytes from the start before searching. A negative offset instead makes the search stop that many bytes from the end. The returned position is always measured from the beginning.

More examples

How the offset changes the search

A positive offset of 9 throws away the first nine bytes before searching, so the last "cat" at 16 is still found but the only "bat" at position 4 is now out of range and the call returns false. The last line confirms that for all-lowercase data strripos and strrpos agree.

Example · php
<?php
$s = 'cat bat cat mat cat';

var_dump(strripos($s, 'CAT'));     // int(16) — the last one
var_dump(strripos($s, 'CAT', 9));  // int(16) — still the last one
var_dump(strripos($s, 'BAT', 9));  // bool(false) — 'bat' is at 4, skipped

var_dump(strripos($s, 'cat', 0) === strrpos($s, 'cat')); // bool(true)

Case-insensitive extension check

Report.PDF reports position 6 and notes.pdf position 5, showing that case is ignored. image.PdF.bak also matches at position 5 even though .bak is the real extension — a reminder that a substring search is not the same as parsing an extension, which pathinfo() would do correctly.

Example · php
<?php
$files = ['Report.PDF', 'notes.pdf', 'image.PdF.bak', 'archive.zip'];

foreach ($files as $f) {
    $p = strripos($f, '.pdf');
    echo $f, ' => ', $p === false ? 'no pdf part' : "'.pdf' at $p", PHP_EOL;
}

Discussion

  • Be the first to comment on this lesson.