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

Extensions

add_filter et sa priorité par défaut, quand deux extensions se disputent un hook

Pour les développeurs qui déboguent un ordre d'exécution de filtres inattendu entre deux extensions accrochées au même hook.

Par WordPress Développement • 6 janvier 2024 • 4 min de lecture • Aucun commentaire
add_filter et sa priorité par défaut, quand deux extensions se disputent un hook

Deux extensions accrochées au même filtre the_content, chacune avec un add_filter() écrit sans troisième argument explicite, produisent un résultat qui dépend d’un facteur que la plupart des développeurs ne consultent jamais : l’ordre dans lequel WordPress a chargé ces deux extensions. Ce comportement n’a rien d’aléatoire, mais il surprend régulièrement en phase de débogage.

Le signal caractéristique de ce type de conflit : une modification de contenu appliquée par une extension de mise en forme automatique du texte n’apparaît qu’à moitié, car une seconde extension de balisage de liens externes s’exécute avant elle et modifie déjà la structure HTML que la première attend intacte.

Rappel du fonctionnement de add_filter

La signature de add_filter() comporte quatre paramètres : le nom du hook, le callback, la priorité (par défaut 10) et le nombre d’arguments acceptés par le callback (par défaut 1). C’est le troisième paramètre, la priorité, qui détermine l’ordre d’exécution relatif entre plusieurs callbacks accrochés au même hook.

add_filter( 'the_content', 'extension_a_mise_en_forme' );          // priorité 10 implicite
add_filter( 'the_content', 'extension_b_baliser_liens_externes' ); // priorité 10 implicite

Les deux extensions ci-dessus utilisent la même priorité par défaut, 10. Dans ce cas précis, WordPress exécute les callbacks de même priorité dans l’ordre où ils ont été enregistrés, ce qui dépend lui-même de l’ordre de chargement des extensions, généralement alphabétique sur le nom de leur dossier, sans garantie absolue selon la configuration du site.

Diagnostiquer l’ordre réel d’exécution

L'essentiel à retenir : La priorité par défaut de add_filter est 10, identique pour tous ; Deux extensions à priorité égale s'exécutent dans l'ordre de chargement ; Le troisième argument de add_filter fixe le nombre d'arguments transmis

Plutôt que de deviner, l’ordre réel d’exécution des callbacks sur un hook donné s’inspecte directement via la variable globale $wp_filter, qui contient la structure interne de tous les hooks enregistrés :

global $wp_filter;
$callbacks = $wp_filter['the_content']->callbacks;
ksort( $callbacks );

foreach ( $callbacks as $priorite => $groupe ) {
    foreach ( $groupe as $detail ) {
        error_log( sprintf( 'Priorité %d : %s', $priorite, print_r( $detail['function'], true ) ) );
    }
}

Cette inspection, placée temporairement dans un fichier de débogage ou exécutée via wp shell en ligne de commande, révèle précisément quels callbacks sont accrochés à quelle priorité, dans quel ordre, sur le hook concerné.

Corriger en fixant une priorité explicite

La correction consiste à choisir explicitement une priorité qui exprime l’intention réelle : la mise en forme du texte doit précéder le balisage des liens, car elle peut restructurer des paragraphes que le balisage de liens doit ensuite analyser tel quel.

add_filter( 'the_content', 'extension_a_mise_en_forme', 5 );
add_filter( 'the_content', 'extension_b_baliser_liens_externes', 20 );

Fixer une priorité plus basse (5) pour la mise en forme garantit son exécution avant le balisage des liens (20), quel que soit l’ordre de chargement des deux extensions. Le choix des valeurs elles-mêmes reste arbitraire : ce qui compte est l’écart suffisant entre les deux pour laisser de la marge à une troisième extension qui s’insérerait un jour entre les deux.

Le piège du nombre d’arguments oublié

Un second piège fréquent, lié mais distinct, concerne le quatrième paramètre de add_filter() : si le callback attend plusieurs arguments du hook (par exemple $content et $post_id sur un hook qui transmet les deux), il faut déclarer explicitement ce nombre, sinon WordPress ne transmet que le premier argument au callback, silencieusement, sans avertissement.

add_filter( 'extension_contenu_personnalise', 'ma_fonction', 10, 2 );

function ma_fonction( $contenu, $post_id ) {
    // $post_id serait null sans le "2" ci-dessus, sur un hook qui le transmet.
    return $contenu;
}

Ce que ce diagnostic ne couvre pas

  • Cet article traite de l’ordre d’exécution technique entre deux callbacks explicitement enregistrés, pas des idées reçues sur le fonctionnement général des hooks WordPress.
  • Il ne couvre pas la désinscription d’un callback avec remove_filter(), qui exige de connaître la priorité exacte utilisée à l’enregistrement pour fonctionner.

Le réflexe que je recommande : dès qu’une extension modifie une donnée déjà modifiable par d’autres (contenu, requête, en-têtes), fixer une priorité explicite dès l’écriture, plutôt que de laisser la valeur par défaut décider d’un ordre qui n’a jamais été choisi consciemment.

En résumé

La priorité par défaut de add_filter(), fixée à 10 pour toute extension qui ne la précise pas, transforme l’ordre de chargement des extensions en facteur déterminant d’un comportement qui devrait rester prévisible. Fixer une priorité explicite, avec une marge suffisante, élimine cette dépendance silencieuse à un ordre de chargement non maîtrisé.

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