strpos($haystack, $needle) retorna a posição do primeiro $needle dentro de $haystack, contada a partir de 0, ou false se ele não estiver lá. Sempre teste o resultado com !== false, porque uma correspondência no início retorna 0.
Se você só precisa de uma resposta sim ou não no PHP 8, o str_contains() é mais claro. Use o strpos() quando a posição importar.
Sintaxe
strpos(string $haystack, string $needle, int $offset = 0): int|false
A busca diferencia maiúsculas e minúsculas. $offset diz onde começar a procurar; um offset negativo conta a partir do fim da string.
A armadilha do !== false
0 e false são iguais na comparação frouxa (==). Uma correspondência na posição 0 é, portanto, tratada como "não encontrado" por qualquer verificação que não seja estrita.
A mesma regra vale para stripos(), strrpos() e array_search(), que podem todos retornar 0 para uma correspondência real.
Busca sem diferenciar maiúsculas com stripos
O stripos() recebe os mesmos argumentos e ignora maiúsculas e minúsculas em letras ASCII.
Encontrar a última ocorrência com strrpos
O strrpos() retorna a posição da última correspondência. É o jeito padrão de pegar a extensão de um arquivo ou o último segmento de um caminho.
Para nomes de arquivos especificamente, pathinfo($file, PATHINFO_EXTENSION) faz isso por você. Cortar a string na posição é explicado na página sobre substr().
Começar a busca num offset
O terceiro argumento pula o começo da string. Um offset negativo começa essa quantidade de caracteres antes do fim.
Encontrar todas as ocorrências
O strpos() encontra uma correspondência. Faça um loop e mova o offset para depois de cada correspondência para encontrar todas:
Só a contagem? substr_count($text, 'the') é mais curto. Para padrões, preg_match_all() com PREG_OFFSET_CAPTURE retorna cada correspondência com a posição.
Texto em japonês: posição em bytes ou em caracteres
O strpos() encontra texto multibyte corretamente, mas o número que retorna está em bytes. Kana e kanji comuns ocupam 3 bytes cada em UTF-8, então num texto todo em japonês a posição em bytes é três vezes a posição em caracteres, e num texto misturado as duas se afastam de formas menos óbvias. O mb_strpos() retorna caracteres, que é o que o mb_substr() espera.
Misturar os dois é um bug clássico: passar um resultado do strpos() para o mb_substr() começa longe demais na string. Use strpos com substr, e mb_strpos com mb_substr.
Perguntas frequentes
O que o strpos() retorna no PHP?
A posição da primeira correspondência como inteiro, contada a partir de 0, ou false se a agulha não for encontrada. strpos('hello', 'l') retorna 2.
Por que preciso de !== false com o strpos()?
Porque uma correspondência logo no início retorna 0, e 0 == false é verdadeiro. if (strpos($s, 'a')) trata uma correspondência na posição 0 como "não encontrado". Compare sempre com strpos($s, 'a') !== false.
Qual a diferença entre strpos, stripos e strrpos?
O strpos() encontra a primeira correspondência e diferencia maiúsculas e minúsculas. O stripos() encontra a primeira ignorando a diferença. O strrpos() encontra a última. O strripos() encontra a última ignorando a diferença.
Devo usar strpos ou str_contains para verificar se uma string contém um texto?
No PHP 8, use str_contains($haystack, $needle), que retorna um simples true ou false e não tem a armadilha da posição 0. Use strpos() quando precisar da posição em si.
Como uso strpos com texto japonês?
O strpos() encontra texto japonês corretamente, mas retorna uma posição em bytes. Se você passar a posição para o mb_substr() ou mostrá-la a um usuário, use mb_strpos(), que retorna a posição em caracteres.