str_contains no PHP 8: parar de comparar strpos com !== false

Código cheio de strpos comparado com !== false é herança de PHP 5. O PHP 8 trouxe str_contains, str_starts_with e str_ends_with: devolvem bool de verdade e acabam com o esquecimento clássico do !== que transforma posição zero em falso.

Antes e depois

// PHP 7.4
if (strpos($ua, 'Googlebot') !== false) { ... }
if (substr($rota, 0, 7) === '/admin/') { ... }
if (substr($arquivo, -5) === '.webp') { ... }

// PHP 8.3
if (str_contains($ua, 'Googlebot')) { ... }
if (str_starts_with($rota, '/admin/')) { ... }
if (str_ends_with($arquivo, '.webp')) { ... }

O bug que sempre aparece em revisão de código é if (strpos($rota, ‘/admin/’)) sem comparação nenhuma. Quando a agulha está no começo da string, strpos devolve 0, o if trata como falso e a regra some. Com str_starts_with isso não tem como acontecer.

As três são sensíveis a maiúsculas, igual strpos. Se o trecho antigo usava stripos, trocar direto por str_contains muda o comportamento: aí é str_contains(strtolower($a), strtolower($b)), ou mb_strtolower quando tem acento no meio.

Ainda tem servidor no 7.4?

Em projeto legado que roda em várias hospedagens eu escrevo o código novo e carrego o polyfill cedo, antes de qualquer coisa que use as funções:

if (!function_exists('str_contains')) {
    function str_contains(string $palheiro, string $agulha): bool {
        return $agulha === '' || strpos($palheiro, $agulha) !== false;
    }
}

Se o projeto usa Composer, prefira o pacote symfony/polyfill-php80: cobre as três funções de uma vez e sai de cena sozinho quando o servidor sobe de versão.

Um detalhe do comportamento com agulha vazia: str_contains($texto, ”) devolve true sempre, e str_starts_with também. Se você monta o termo a partir de um campo de busca que pode chegar em branco, valide antes, senão o filtro deixa passar a lista inteira.

Um grep por “!== false” no projeto costuma render uma limpeza rápida e sem risco de regressão.

Dúvidas? Faça um comentário logo abaixo ou envie uma mensagem clicando aqui.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *