# str_contains() remplace un strpos() !== false depuis PHP 8.0

> « if ( false !== strpos( $texte, $mot ) ) » a longtemps été le seul moyen de tester une sous-chaîne en PHP. Depuis la version 8.0, une fonction dédiée dit enfin ce qu'elle fait.

- Auteur : Clément Hadrot
- Publié le : 2025-12-23
- Mis à jour le : 2025-12-23
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/str-contains-remplace-strpos-depuis-php80/

## L’essentiel

- Teste une sous-chaîne sans comparaison stricte à false
- Retourne un booléen direct, plus lisible qu'un strpos détourné
- Disponible nativement depuis PHP 8.0

`if ( false !== strpos( $texte, $mot ) ) { ... }` : cette tournure a occupé des milliers de bases de code PHP pendant des années, WordPress y compris, faute d'alternative native. `strpos()` retourne la position de la première occurrence trouvée, ou `false` si la sous-chaîne est absente — et comme la position `0` est une valeur falsy en PHP, comparer le résultat à `false` avec l'opérateur strict `!==` était la seule façon fiable de tester une présence, y compris en tout début de chaîne.

Depuis PHP 8.0, cette gymnastique n'est plus nécessaire : `str_contains( string $haystack, string $needle )` retourne directement un booléen, sans piège de comparaison, et dit explicitement ce que le code cherche à savoir.

## Pourquoi l'ancienne forme posait un vrai risque

Le bug classique consistait à écrire `if ( strpos( $texte, $mot ) )` sans la comparaison stricte : si `$mot` se trouvait tout au début de `$texte`, à la position `0`, la condition évaluait ce `0` comme faux, alors que la sous-chaîne était bien présente. Ce bug ne se manifestait que dans ce cas précis, ce qui le rendait difficile à repérer en test rapide et facile à laisser filer en revue de code.

`str_contains()` élimine ce piège à la racine : elle retourne toujours un booléen véritable, sans valeur intermédiaire ambiguë à interpréter.

## Moderniser une vérification de code existant

> L'essentiel à retenir : Teste une sous-chaîne sans comparaison stricte à false ; Retourne un booléen direct, plus lisible qu'un strpos détourné ; Disponible nativement depuis PHP 8.0

Sur une extension qui vérifie, par exemple, si une chaîne d'agent utilisateur correspond à un robot connu, la modernisation est directe :

```
// Avant PHP 8.0
function est_probablement_un_robot( $user_agent ) {
    return false !== strpos( $user_agent, 'bot' )
        || false !== strpos( $user_agent, 'crawler' );
}

// À partir de PHP 8.0
function est_probablement_un_robot( $user_agent ) {
    return str_contains( $user_agent, 'bot' )
        || str_contains( $user_agent, 'crawler' );
}
```

Le second bloc se lit sans effort supplémentaire, même par quelqu'un qui découvre le code : la fonction annonce directement son résultat, sans qu'il faille se souvenir de la règle de comparaison stricte à appliquer sur un appel à `strpos()`.

## Deux fonctions sœurs arrivées en même temps

PHP 8.0 a introduit `str_contains()` aux côtés de deux autres fonctions qui couvrent des besoins voisins :

- `str_starts_with( string $haystack, string $needle )` : teste si une chaîne commence par une sous-chaîne donnée.
- `str_ends_with( string $haystack, string $needle )` : teste si une chaîne se termine par une sous-chaîne donnée.
- `str_contains()` : teste une présence n'importe où dans la chaîne, ce qui couvre le besoin le plus général des trois.

Ces trois fonctions remplacent, à elles seules, la grande majorité des usages de `strpos()` détourné en simple test de présence, laissant `strpos()` aux cas où la position exacte de la sous-chaîne importe réellement pour la suite du traitement.

## Vérifier la version minimale avant de moderniser

Avant de remplacer systématiquement un `strpos()` par `str_contains()` dans une extension existante, il reste indispensable de vérifier la version minimale de PHP déclarée dans l'en-tête de l'extension. Utiliser `str_contains()` sur un hébergement encore sous PHP 7.4 provoquerait une erreur fatale à l'exécution, la fonction étant simplement inexistante avant PHP 8.0.

> Avant toute modernisation de ce type, vérifier la ligne « Requires PHP » de l'en-tête de l'extension : c'est elle qui indique si str_contains() peut être utilisée sans risque sur l'ensemble du parc d'hébergement visé.

## Un détail qui compte : la chaîne vide

Un comportement mérite d'être vérifié avant de généraliser le remplacement : `str_contains( $texte, '' )` retourne toujours `true`, quelle que soit la valeur de `$texte`, puisqu'une chaîne vide est considérée comme présente partout. C'est également le comportement historique de `strpos()` sur une aiguille vide, qui renvoie `0` plutôt que `false` — donc rien ne change ici, mais le cas mérite d'être gardé en tête si un attribut ou un paramètre peut légitimement arriver vide dans le code modernisé.

## En résumé

`str_contains()` n'ajoute aucune capacité qu'un `strpos()` comparé strictement à `false` ne couvrait déjà, mais elle élimine un piège de comparaison connu et rend l'intention du code immédiatement lisible. Sur une base de code visant PHP 8.0 ou une version plus récente, il n'y a plus de raison de conserver l'ancienne tournure, sauf dans les cas où la position exacte de la sous-chaîne trouvée reste nécessaire pour la suite du traitement.
