stripos

Finds the position of the first case-insensitive occurrence of a substring in a string.

Signature
stripos(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= 0Where in haystack to start searching. Negative values start that many characters from the end.

Return value

int|falseThe zero-based position of the first case-insensitive match, or false if the needle is 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; only ASCII case folding is performed.
  • PHP 8.0.0needle may now be an empty string, which returns the offset.
  • PHP 8.0.0Passing an int as needle is no longer supported; it was deprecated in 7.3.0.
  • PHP 7.1.0Negative offset values are supported.

stripos is strpos with ASCII case folding: it returns the zero-based byte offset of the first match, ignoring letter case, or false when the needle is absent.

When to reach for it

Use it when you need to know where a case-insensitive match starts — to slice around it, to highlight it, or to walk every occurrence by feeding the previous position back in as $offset. If you only need a yes/no answer, str_contains(strtolower($h), strtolower($n)) or a stristr call reads better.

What trips people up

The famous trap: a match at the very start returns 0, which is falsy. if (stripos($h, $n)) silently misses matches at position 0. Always write !== false or === 0.

Since PHP 8.0 an $offset larger than the haystack throws a ValueError instead of warning and returning false, so guard offsets you compute from user input.

Folding is ASCII-only since PHP 8.2 and is no longer locale-sensitive, so É will not match é. The returned position is a byte offset, which does not line up with mb_substr() on multi-byte text — use mb_stripos() there.

Example

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

When to use it

  • Find where a search term appears in a document so it can be wrapped in a highlight tag
  • Detect a keyword in a subject line regardless of how the sender capitalised it
  • Walk every case-insensitive occurrence of a term by advancing the offset in a loop

Frequently asked questions

What is the difference between stripos and strpos?

stripos ignores ASCII letter case while strpos is case-sensitive. Both return the zero-based byte position of the first match, or false when there is no match.

Why does if (stripos($a, $b)) not work?

Because a match at the start of the string returns 0, which PHP treats as false. Write stripos($a, $b) !== false instead.

How do I check case-insensitively whether a string contains a substring?

Use stripos($haystack, $needle) !== false, or str_contains(strtolower($haystack), strtolower($needle)) if you prefer a boolean-returning function.

More examples

Finding every occurrence

Prints 0: Cat, 5: cat and 21: CAT. Feeding the previous position plus the needle length back in as the offset walks the whole string; the !== false test is what makes the match at position 0 work.

Example · php
<?php
$text = 'Cat, caterpillar and CATALOG';
$pos  = 0;
while (($pos = stripos($text, 'cat', $pos)) !== false) {
    echo $pos, ': ', substr($text, $pos, 3), "\n";
    $pos += 3;
}

Negative offsets

A negative offset starts the search that many bytes from the end, so -3 finds the final 'a' at index 6. strripos reaches the same result by searching backwards from the end.

Example · php
<?php
$s = 'abcABCabc';
var_dump(stripos($s, 'a'));      // int(0)
var_dump(stripos($s, 'a', 1));   // int(3)
var_dump(stripos($s, 'a', -3));  // int(6)
var_dump(strripos($s, 'a'));     // int(6)

Guarding an out-of-range offset

An offset past the end of the haystack throws a ValueError as of PHP 8.0 rather than returning false. Clamping the offset with min() keeps the call safe and returns bool(false) for the missing needle.

Example · php
<?php
$s = 'short';
try {
    stripos($s, 'x', 99);
} catch (ValueError $e) {
    echo 'ValueError: ', $e->getMessage(), "\n";
}
var_dump(stripos($s, 'x', min(2, strlen($s))));

Discussion

  • Be the first to comment on this lesson.