# str_contains() et str_starts_with() simplifient la validation d’un attribut

> preg_match('/^http/', $valeur) fonctionne, mais reste plus lourd à lire qu'une fonction native dédiée. Deux fonctions PHP 8 remplacent avantageusement ces regex fragiles.

- Auteur : WordPress Développement
- Publié le : 2022-01-16
- Mis à jour le : 2022-01-16
- Catégorie : Blocs Gutenberg
- URL : https://www.wpmoderne.fr/blocs/str-contains-str-starts-with-validation-attribut/

## L’essentiel

- str_starts_with remplace une regex d'ancrage de début de chaîne
- str_contains remplace strpos combiné à une comparaison stricte
- Nécessitent PHP 8.0 minimum, disponible depuis WordPress 5.6

`preg_match( '/^http/', $valeur )` : cette ligne, écrite pour vérifier qu'un attribut de bloc commence bien par un protocole HTTP avant de l'utiliser comme URL, fonctionne parfaitement. Elle reste pourtant plus lourde à lire et plus coûteuse à exécuter qu'une simple comparaison de chaîne, pour un besoin qui ne demande aucune expression régulière.

Depuis PHP 8.0, deux fonctions natives couvrent directement ces besoins fréquents de validation d'attribut : `str_starts_with()` et `str_contains()`. WordPress 5.6, sorti en décembre 2020, a ajouté la compatibilité officielle avec PHP 8, rendant ces fonctions utilisables sans réserve sur un site à jour.

## str_starts_with() contre une regex d'ancrage

Vérifier qu'une chaîne commence par un préfixe précis se faisait auparavant de plusieurs façons, chacune avec ses inconvénients : une regex avec l'ancre `^`, ou une comparaison via `substr()` et `===`. La nouvelle fonction rend l'intention explicite dès la lecture :

```
function valider_url_attribut( string $valeur ): bool {
    return str_starts_with( $valeur, 'https://' )
        || str_starts_with( $valeur, 'http://' );
}
```

Comparée à une regex équivalente, cette écriture évite la compilation d'un motif à chaque appel et rend le code lisible sans connaissance préalable des expressions régulières, un avantage réel pour une équipe qui compte des profils juniors.

## str_contains() pour une recherche simple

> L'essentiel à retenir : str_starts_with remplace une regex d'ancrage de début de chaîne ; str_contains remplace strpos combiné à une comparaison stricte ; Nécessitent PHP 8.0 minimum, disponible depuis WordPress 5.6

De la même façon, tester la présence d'une sous-chaîne quelque part dans un texte se faisait via `strpos()`, dont le retour nécessite une comparaison stricte avec `!== false` pour éviter un piège classique (une position à l'index zéro évaluée comme fausse par PHP) :

```
// avant : piège fréquent si l'on oublie la comparaison stricte
if ( strpos( $valeur, 'youtube.com' ) !== false ) {
    // ...
}

// après : aucune ambiguïté possible
if ( str_contains( $valeur, 'youtube.com' ) ) {
    // ...
}
```

Ce piège de `strpos()` a généré d'innombrables bugs dans du code WordPress au fil des années, en particulier lorsqu'une sous-chaîne recherchée se trouve juste au début de la chaîne testée. `str_contains()` retourne un booléen franc, sans cas particulier à connaître.

## Application dans un bloc : valider un attribut d'intégration vidéo

Un bloc « vidéo intégrée » qui accepte une URL saisie librement par le rédacteur peut valider, côté PHP, que l'URL correspond bien à un service connu avant de générer l'intégration :

```
function rendre_bloc_video( array $attributs ) {
    $url = $attributs['url'] ?? '';

    if ( str_contains( $url, 'youtube.com' ) || str_contains( $url, 'youtu.be' ) ) {
        return generer_iframe_youtube( $url );
    }

    if ( str_contains( $url, 'vimeo.com' ) ) {
        return generer_iframe_vimeo( $url );
    }

    return '<p>Service vidéo non reconnu.</p>';
}
```

Cette écriture reste lisible même pour un développeur qui découvre le bloc pour la première fois, contrairement à une chaîne d'appels `preg_match()` aux motifs peu explicites.

## Une vigilance nécessaire sur les hébergements

- Ces fonctions n'existent pas sur PHP 7.4 ou antérieur : un bloc destiné à être diffusé largement doit vérifier la version PHP minimale supportée avant de les utiliser sans filet.
- Pour une extension distribuée sur le répertoire officiel, une vérification de compatibilité (`Requires PHP` dans l'en-tête de l'extension) évite une fatale error sur un hébergement resté en PHP 7.
- Un polyfill existe pour les projets qui doivent encore supporter PHP 7.4, mais il ajoute une dépendance supplémentaire à gérer.

## Ce que change réellement cette migration

Le gain n'est pas spectaculaire en performance pure sur un seul appel, mais il l'est en lisibilité et en fiabilité : chaque fonction porte un nom qui décrit exactement son comportement, sans risque de confusion sur la valeur de retour. Sur un bloc qui valide plusieurs attributs à chaque rendu, cette lisibilité additionnée facilite grandement les relectures de code entre collègues.

> Sur nos revues de code depuis le passage officiel de nos hébergements à PHP 8, tout `strpos() !== false` repéré est désormais systématiquement proposé en remplacement par `str_contains()`, sans exception.

## En résumé

`str_starts_with()` et `str_contains()` ne révolutionnent rien techniquement, mais elles suppriment un piège de lecture classique et rendent la validation d'attributs de bloc plus directe à écrire comme à relire. Leur adoption suppose simplement de s'assurer que l'environnement d'hébergement tourne bien sur PHP 8 ou une version ultérieure.
