vendredi 25 septembre 2026

À propos

Contact

Extensions

Namespace collisions et préfixage : les erreurs qui coûtent cher en production

Un préfixe trop court, un namespace générique, une fonction globale mal nommée : ces erreurs de préfixage provoquent des fatal errors difficiles à diagnostiquer.

Par Clément Hadrot • 13 juillet 2022 • 5 min de lecture • Aucun commentaire
Namespace collisions et préfixage : les erreurs qui coûtent cher en production

« Fatal error: Cannot redeclare function() ». Cette ligne, familière à quiconque a géré des sites WordPress à fort volume d’extensions, résume à elle seule tout le risque du préfixage insuffisant. Deux extensions, développées indépendamment, choisissent le même nom court pour une fonction utilitaire, et le site entier s’effondre dès que les deux sont actives simultanément.

Cet article recense les pièges de collision les plus fréquents rencontrés en dix ans de maintenance d’extensions WordPress, avec pour chacun une explication de la cause réelle et la correction à appliquer.

Le piège du préfixe trop court

Un préfixe de deux ou trois lettres (ac_, wpx_) semble suffisant tant qu’on ne réfléchit pas au nombre d’extensions qui peuvent cohabiter sur un même site. Sur un site institutionnel ou e-commerce mature, il n’est pas rare de dépasser cinquante extensions actives. Un préfixe court multiplie mécaniquement le risque de collision.

// Risqué : "acme_" est court et générique
function acme_log( $message ) { /* ... */ }

// Plus sûr : un préfixe long et spécifique à l'extension, pas à l'agence
function acmecrm_synchroniser_log( $message ) { /* ... */ }

Le namespace PHP résout ce problème de façon définitive (voir notre article sur l’architecture avec PSR-4), mais toute portion de code qui doit rester dans le scope global — fonctions de template destinées aux thèmes, callbacks enregistrés par nom de chaîne dans certains hooks anciens — reste exposée au risque et doit conserver un préfixage rigoureux.

Les constantes, grandes oubliées du préfixage

Un développeur soigneux sur ses noms de fonctions oublie fréquemment d’appliquer la même rigueur aux constantes, qui vivent pourtant dans le même scope global partagé par toutes les extensions actives.

// Collision potentielle : VERSION est un nom générique
define( 'VERSION', '2.1.0' );

// Correct
define( 'ACMECRM_VERSION', '2.1.0' );

Une collision sur une constante ne provoque pas une fatale error immédiate comme pour une fonction dupliquée : PHP émet un simple avertissement (« Constant already defined ») et conserve la première valeur définie. C’est en réalité plus dangereux qu’un plantage franc, car le bug reste silencieux : une extension continue de fonctionner avec la mauvaise valeur de version ou de configuration, sans qu’aucune alerte visible ne signale le problème avant un comportement inattendu en production.

L'essentiel à retenir : Un préfixe de 3 lettres n'est jamais assez unique ; Les constantes globales échappent souvent au namespace ; function_exists ne protège pas d'une vraie collision de version

function_exists : une fausse sécurité

Certains développeurs entourent leurs déclarations de fonctions d’un function_exists() pour « éviter les erreurs de redéclaration ». Ce réflexe masque le symptôme sans traiter la cause, et peut provoquer un bug bien plus insidieux qu’une fatale error.

if ( ! function_exists( 'acme_calculer_remise' ) ) {
    function acme_calculer_remise( $prix, $pourcentage ) {
        return $prix * ( 1 - $pourcentage / 100 );
    }
}

Si une autre extension a déjà déclaré une fonction du même nom, avec une logique différente (par exemple un pourcentage exprimé en décimal plutôt qu’en entier), ce garde-fou empêche la fatale error mais votre extension utilisera silencieusement la fonction de l’autre extension, avec des résultats de calcul erronés et aucune erreur visible pour alerter qui que ce soit. Un plantage explicite, aussi désagréable soit-il, reste souvent préférable à une corruption silencieuse de données métier.

Notre règle en revue de code : function_exists autour d’une déclaration de fonction est acceptable uniquement quand la fonction sert de point d’extension volontaire et documenté (permettre à un thème de la surcharger), jamais comme filet de sécurité contre une collision de nommage accidentelle.

Les classes globales, même piège

Avant l’adoption des namespaces PHP, deux extensions qui déclarent chacune une classe Logger ou Settings dans le scope global entrent en collision de la même façon qu’avec des fonctions. Les namespaces éliminent structurellement ce risque, à condition que le namespace racine choisi soit lui-même suffisamment spécifique : un namespace Plugin\ reste tout aussi risqué qu’un préfixe de fonction générique.

// Namespace trop générique, risque de collision indirecte via des outils
// d'analyse ou des extensions qui scannent les namespaces actifs
namespace Plugin;

// Préférable
namespace AcmeCrm\Synchronisation;

Les hooks eux-mêmes peuvent collisionner

Un nom de hook personnalisé (do_action( 'sync_termine' )) trop générique peut être déclenché ou intercepté involontairement par une autre extension qui a choisi le même nom pour un usage complètement différent. La convention à appliquer est identique à celle des fonctions : préfixer systématiquement.

// Risqué
do_action( 'sync_termine' );

// Sûr
do_action( 'acmecrm_synchronisation_terminee' );

Diagnostiquer une collision en production

Quand une fatale error de redéclaration survient, WP-CLI aide à identifier rapidement le coupable sans devoir désactiver les extensions une par une en production :

wp plugin list --status=active --field=name
# Puis, en environnement de test, désactivation par dichotomie
wp plugin deactivate --all
wp plugin activate mon-extension autre-extension

Le message d’erreur PHP lui-même précise généralement le fichier et la ligne de la première déclaration, ce qui permet souvent d’identifier directement l’extension fautive sans même recourir à cette méthode par élimination.

En résumé

Le préfixage rigoureux — fonctions, constantes, classes hors namespace, noms de hooks — reste une discipline de base trop souvent négligée par excès de confiance. Un namespace PHP bien choisi élimine la plupart de ces risques pour le code orienté objet, mais tout ce qui reste dans le scope global exige la même vigilance qu’il y a quinze ans.

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