vendredi 25 septembre 2026

À propos

Contact

Extensions

Strauss et PHP-Scoper : préfixer les dépendances Composer d’une extension

Deux extensions du même site embarquent Guzzle, mais dans deux versions incompatibles. Résultat : une erreur fatale de classe déjà déclarée. Voici comment l'éviter dès la construction du plugin.

Par Clément Hadrot • 6 juillet 2022 • 4 min de lecture • Aucun commentaire
Strauss et PHP-Scoper : préfixer les dépendances Composer d'une extension

Sur un site e-commerce utilisant à la fois une extension de facturation et une extension de synchronisation avec un comparateur de prix, développées par deux prestataires différents mais toutes deux construites avec Composer et embarquant la bibliothèque Guzzle, le site s’est mis à afficher une erreur fatale : Cannot declare class GuzzleHttp\Client, because the name is already in use. Les deux extensions embarquaient des versions incompatibles de la même bibliothèque, chargées dans le même espace de noms global PHP.

WordPress n’offre aucun isolement natif entre les dépendances Composer de plugins distincts : tout tourne dans le même processus PHP, avec un seul espace de noms partagé. La solution consiste à préfixer les espaces de noms des bibliothèques embarquées, pour que chaque extension transporte sa propre version sous un nom unique.

Pourquoi Composer seul ne suffit pas

Composer gère très bien la résolution de versions au sein d’un seul projet, mais WordPress n’est pas un projet Composer unique : chaque extension embarque généralement son propre répertoire vendor/, chargé indépendamment via son propre autoload.php. Rien n’empêche deux extensions de déclarer, dans deux fichiers distincts, la même classe GuzzleHttp\Client, avec des implémentations différentes selon la version.

La seule façon fiable d’éviter ce type de collision consiste à renommer l’espace de noms de chaque bibliothèque embarquée, pour qu’elle devienne unique à chaque extension, même si le code source original est strictement identique d’un plugin à l’autre.

Strauss : l’outil pensé pour l’écosystème WordPress

L'essentiel à retenir : WordPress ne fournit aucun isolement entre les dépendances Composer de plugins différents ; Préfixer les espaces de noms des bibliothèques embarquées évite les collisions de classes ; Le build final ne doit jamais dépendre d'une exécution manuelle oubliable

Strauss est un outil né spécifiquement pour ce contexte WordPress, en complément de Composer plutôt qu’en remplacement. Il copie les dépendances déclarées dans une section dédiée du composer.json, et réécrit leurs espaces de noms avec un préfixe propre à l’extension.

{
    "require": {
        "guzzlehttp/guzzle": "^7.4"
    },
    "extra": {
        "strauss": {
            "namespace_prefix": "KaolinComparateur\\Dependencies\\",
            "classmap_prefix": "KaolinComparateur_",
            "target_directory": "vendor-prefixed",
            "packages": [
                "guzzlehttp/guzzle"
            ]
        }
    }
}

Après exécution de Strauss, les classes de Guzzle ne sont plus accessibles sous GuzzleHttp\Client, mais sous KaolinComparateur\Dependencies\GuzzleHttp\Client, un espace de noms qu’aucune autre extension n’a de raison de réutiliser à l’identique.

use KaolinComparateur\Dependencies\GuzzleHttp\Client;

$client = new Client( array( 'timeout' => 10 ) );

Intégrer Strauss dans le processus de build

Le piège le plus fréquent avec Strauss n’est pas sa configuration, mais son oubli : si l’exécution du préfixage dépend d’une commande lancée manuellement par un développeur avant chaque publication, elle finit tôt ou tard par être oubliée, livrant une version non préfixée en production.

{
    "scripts": {
        "post-install-cmd": "strauss",
        "post-update-cmd": "strauss"
    }
}

Brancher Strauss sur les scripts Composer post-install-cmd et post-update-cmd garantit que le préfixage se produit systématiquement à chaque installation ou mise à jour des dépendances, sans dépendre de la mémoire du développeur qui exécute la commande.

PHP-Scoper : une alternative plus large

PHP-Scoper vise un objectif proche, mais avec un périmètre plus large : il peut préfixer l’ensemble du code d’un projet, pas uniquement ses dépendances tierces, et s’intègre bien dans un pipeline de build produisant un fichier PHAR ou une archive de distribution complète.

  • Strauss reste plus simple à intégrer pour le cas courant d’une extension WordPress qui souhaite seulement isoler ses dépendances
  • PHP-Scoper convient mieux à des projets plus complexes, où l’ensemble du code, y compris propriétaire, doit être isolé dans un espace de noms unique
  • Les deux outils reposent sur le même principe de réécriture statique des espaces de noms à la construction, jamais à l’exécution

Préfixer ses propres classes métier n’est généralement pas nécessaire : un bon préfixe de fonction et de classe suffit. Le préfixage automatisé concerne avant tout les bibliothèques tierces qu’on ne maîtrise pas et qui risquent de se retrouver, sans le vouloir, embarquées ailleurs sur le même site.

En résumé

Le conflit rencontré sur ce site e-commerce n’avait rien d’exceptionnel : c’est un scénario qui se reproduit dès qu’un site cumule plusieurs extensions construites indépendamment avec Composer, sans isolation des dépendances. Strauss, intégré directement au processus de build via les scripts Composer, a permis de livrer une nouvelle version de l’extension de comparateur qui coexiste désormais sans le moindre conflit avec l’extension de facturation, quelle que soit la version de Guzzle que cette dernière embarque de son côté.

Partager :

À propos de l'auteur

Clément Hadrot

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

Voir tous ses articles

Dans la même veine

À lire aussi