Searching Within Strings

strpos() returns the byte offset of the first match or false; stripos() ignores case and strrpos() finds the last match. A match at offset 0 is falsy, so if (strpos(...)) fails whenever the needle starts the string. PHP 8.0's str_contains(), str_starts_with() and str_ends_with() return a plain bool and remove the trap; use them whenever you do not need the position.

Position functions and the PHP 8.0 predicates (search.php)PHP
<?php
$path = 'Books/Report.2026.PDF';
if (!strpos($path, 'Books')) { echo "strpos returned 0, which is falsy\n"; }
echo json_encode([str_contains($path, 'Report'), str_starts_with($path, 'Books/'),
    str_ends_with(strtolower($path), '.pdf')]), ' ';
echo stripos($path, 'report'), ' ', strrpos($path, '.'), ' ',
    substr($path, strrpos($path, '.') + 1), "\n";
$email = 'grace.hopper@example.com';
echo strstr($email, '@', true), ' | ', strstr($email, '@'), ' | ', strrchr($email, '.'), ' | ',
    strpbrk('Order #A-17', '0123456789'), ' | ', strspn('2026-09-23', '0123456789'), "\n";
Output
strpos returned 0, which is falsy
[true,true,true] 6 17 PDF
grace.hopper | @example.com | .com | 17 | 4

strstr() returns the string from the match on, or the part before it with true; strrchr() starts at the last occurrence of a character, strpbrk() at the first of a set, and strspn() counts leading bytes from a set. If you keep strpos(), compare with !== false.