Le WordPress d'aujourd'hui, décodé pour les développeurs

SEO & GEO

« count(): Argument doit être de type Countable » casse un sitemap sous PHP 8

Un script maison de sitemap qui tournait sans souci depuis des années s'effondre après une migration vers PHP 8. Diagnostic d'une régression de compatibilité fréquente.

Par WordPress Développement • 28 janvier 2021 • 4 min de lecture • Aucun commentaire
« count(): Argument doit être de type Countable » casse un sitemap sous PHP 8

Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, int given. Ce message, apparu du jour au lendemain après une montée de version PHP 7.4 vers 8.0, a mis à l’arrêt le script maison de génération de sitemap d’un site catalogue. Aucune modification de code n’avait pourtant été faite sur ce script depuis des mois.

Ce cas illustre un piège classique de la migration vers PHP 8 : du code qui fonctionnait « silencieusement mal » depuis longtemps devient soudain bloquant, parce que PHP a changé la sévérité d’une erreur qu’il tolérait auparavant. Voici comment diagnostiquer et corriger ce cas précis, sans toucher à la question de la limite des 50 000 URL par fichier, qui est un tout autre sujet.

Symptôme

Le script de sitemap, exécuté via une tâche planifiée wp_schedule_event, générait chaque nuit un fichier XML listant les produits du catalogue. Après la migration serveur vers PHP 8.0, l’exécution s’arrête net avec l’erreur ci-dessus, et aucun fichier sitemap.xml n’est produit cette nuit-là. Le fichier de la veille reste en place, ce qui masque le problème pendant plusieurs jours avant qu’il ne soit repéré.

Diagnostic

L'essentiel à retenir : PHP 8 transforme un avertissement silencieux en erreur fatale ; count() sur une valeur non tableau devient une TypeError bloquante ; Le correctif consiste à sécuriser le type avant chaque appel à count()

Le code fautif ressemblait à ceci :

function generer_urls_produits() {
    $produits = get_transient( 'cache_produits_sitemap' );
    // Le transient a expiré : $produits vaut false, pas un tableau
    if ( count( $produits ) > 0 ) {
        foreach ( $produits as $produit ) {
            // construction du sitemap
        }
    }
}

Avant PHP 8, appeler count() sur une valeur qui n’est ni un tableau ni un objet implémentant l’interface Countable (comme false ou null) déclenchait un simple avertissement (Warning), et la fonction renvoyait 1. Le script continuait de s’exécuter, produisant potentiellement un sitemap incomplet, mais sans jamais s’arrêter. Depuis PHP 8.0, ce même appel déclenche une TypeError fatale qui interrompt immédiatement le script.

Correctif

La solution consiste à sécuriser le type de la variable avant tout appel à count(), en s’assurant qu’elle est bien un tableau :

function generer_urls_produits() {
    $produits = get_transient( 'cache_produits_sitemap' );
    if ( ! is_array( $produits ) ) {
        $produits = array();
    }
    if ( count( $produits ) > 0 ) {
        foreach ( $produits as $produit ) {
            // construction du sitemap
        }
    }
}

Cette vérification explicite avec is_array() avant l’appel à count() élimine la cause profonde plutôt que de simplement supprimer l’erreur en désactivant l’affichage des erreurs PHP, ce qui aurait masqué le problème sans le résoudre.

Où chercher d’autres occurrences du même piège

  • Toute variable issue d’une fonction pouvant renvoyer false comme get_transient(), get_option() avec une valeur par défaut mal définie, ou un résultat de requête SQL vide
  • Les tableaux issus de json_decode() sans vérification du résultat en cas de JSON invalide, qui renvoie null
  • Les valeurs issues de $_GET ou $_POST passées directement à count() sans validation préalable

Prévention

Avant toute montée de version PHP majeure, un passage du code par WP-CLI avec la commande wp eval-file sur un environnement de préproduction permet de repérer une bonne partie de ces cas. Ajouter une vérification systématique de type avant chaque appel à une fonction comme count(), array_map() ou implode() évite ce genre de régression, qui touche particulièrement le code ancien écrit à une époque où PHP tolérait ces approximations.

La leçon retenue sur ce projet : une migration PHP majeure doit toujours s’accompagner d’une exécution complète des scripts planifiés en environnement de test, pas seulement d’un chargement des pages du site.

En résumé

PHP 8 n’a rien cassé qui fonctionnait correctement : il a simplement cessé de tolérer silencieusement un usage incorrect de count() qui produisait déjà, en creux, des sitemaps parfois incomplets sans que personne ne le remarque. Ce type de régression, purement lié à la sévérité des erreurs et non à une suppression de fonctionnalité, mérite une attention particulière à chaque montée de version PHP.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi