Qu’est-ce qu’un hook ?
Les hooks sont une mise en pratique du modèle de conception appelé Observer pattern. Un hook est un déclencheur d’événements placé dans le code de WordPress sur lequel peuvent s’inscrire des fonctions. A chaque fois que l’exécution d’une requête va passer sur un hook, toutes les fonctions qui y sont inscrites vont être appelées. C’est donc un moyen d’ouvrir des « parenthèses » lors de cette exécution pour y « intercaler » du code spécifique.
WordPress est jalonné de hooks à des moments clefs de son exécution. Les hooks sont pensés afin de permettre d’enrichir et de spécialiser son exécution. C’est principalement sur les hooks que repose la conception des extensions et des thèmes.
De la même manière, les thèmes et extensions implémentent généralement des hooks qui permettent de personnaliser leur propre exécution.
Il existe deux types de hook dans WordPress :
- Les
actions
, qui permettent d’exécuter du code à un moment donné. Par exemple m’envoyer un SMS lorsqu’une commande a été payée sur le site. - Les
filters
, qui permettent de modifier une variable lors de son utilisation. Par exemple raccourcir le titre d’une page lors son affichage s’il est trop long.
Quels sont-ils ?
Il existe une multitude de hooks dans WordPress, de base : la liste officielle.
Ensuite, chaque thème et chaque extension ajoute son propre lot de hooks. Cela est très pratique puisque cela permet de modifier ou d’enrichir leur fonctionnement. Par contre, il peut devenir un peu fastidieux de dénicher celui qui pourra convenir pour votre développement.
Pour les trouver :
- La documentation WordPress ou celle des extensions concernées
- L’utilisation d’extensions comme Query Monitor ou Simply Show Hooks
- La lecture du code, aidée par une recherche des occurrences de
do_action
ou deapply_filters
- Des recherches par mot-clefs sur le web, parcourir ou ouvrir des discussions sur des forums
- Ajouter des traces directement au coeur de WordPress
Query Monitor
Query Monitor est une extension open source et gratuite qui offre un large panel d’outils très pratiques pour faciliter le développement sous WordPress. En bref, il vous permet de décortiquer à peu près tout ce qui se passe lors de l’exécution sous WordPress.
Je ne détaillerai pas tout son fonctionnement, et vous invite plutôt à consulter son site officiel et sa documentation.
Parmi tous les outils qu’il comporte, il est possible d’observer la liste de tous les hooks.
Une fois Query Monitor installé et activé, visiter le menu Hooks, Actions, & Filters
:
Petit détail d’importance : par défaut les filters
, ne sont pas affichés par Query Monitor. Pour activer cet affichage, il faut ajouter une configuration dans le fichier wp-config.php
, comme suit :
Simply Show Hooks
Simply Show Hook est une extension gratuite qui offre la possibilité de voir où les hooks sont appelés directement sur la page WordPress.
La différence avec Query Monitor est son aspect visuel très pratique. Les hooks utilisés sont mis en évidence et donnent des infos lors de leur survol :
Ajouter des traces directement au coeur de WordPress
WordPress gère l’appel des hooks dans le fichier /wp-includes/plugin.php
dans les fonctions apply_filters()
et do_action()
.
Il suffit alors d’ajouter une trace à cet endroit pour lister les hooks qui peuvent être intéressants.
Par exemple, pour retrouver des actions qui sont appelées lorsque WordPress ou des composants sont chargés, en filtrant le nom de l’action sur le terme loaded
:
Traces générées :
Ce simple exemple montre que 4 hooks actions sont appelés :
muplugins_loaded
- puis
plugin_loaded
pour chaque extension activée plugins_loaded
lorsque toutes les extensions sont activées- finalement
wp_loaded
Comment les utiliser ?
Les deux fonctions clefs pour s’inscrire sur un filtre ou une action sont respectivement les suivantes :
add_filter( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 ): true
add_action( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 ): true
Les paramètres :
$hook_name
: le nom du hook sur lequel s’inscrire$callback
: la méthode ou fonction inscrite, qui sera appelée$priority
: la priorité d’appel par rapport aux autres inscriptions sur ce même hook. Plus la priorité est basse, plus l’appel sera effectué tôt.$accepted_args
: le nombre de paramètres de la fonction ou méthode appelée
Je parle de fonction ou de méthode appelée, parce que cela va dépendre du contexte dans lequel est appelé le hook.
Appel direct de fonction
Lorsque l’inscription sur un hook concerne l’appel d’une fonction, cela est relativement simple. Dans l’exemple suivant j’inscris une fonction sur le hook wp_loaded
afin qu’elle soit appelée lorsque WordPress, son thème et ses extensions sont chargés :
Ce code peut être placé dans le fichier functions.php du thème enfant.
Le nom de la fonction appelée est passée directement en paramètre de la fonction add_action()
: 'wpblog_wp_loaded'
Appel d’une méthode de classe
Lors d’un développement qui commence à prendre de l’ampleur, typiquement lors de la conception d’une extension, une architecture évoluée va comporter des classes.
Si l’inscription sur un hook concerne l’appel d’une méthode au sein d’une classe :
Dans ce cas, le nom de la méthode appelée doit être accompagné d’une référence à l’objet qui la contient.
Cela est résolu de la manière suivante : array( $test, 'action_wp_loaded')
Appel d’une méthode interne
Un autre cas possible pour une classe est l’inscription d’une méthode interne sur un hook:
Dans ce cas, le mot clef $this
peut être utilisé pour faire référence à l’objet qui la contient, c’est-à-dire elle-même.
Cela devient : array( $this, 'action_wp_loaded' )
Et pour s’en défaire ?
En principe c’est simple puisqu’il suffit d’utiliser les fonctions :
remove_filter( string $hook_name, callable|string|array $callback, int $priority = 10 ): bool
remove_action( string $hook_name, callable|string|array $callback, int $priority = 10 ): bool
Ça fonctionne facilement si l’inscription est faire sur une fonction ou une méthode de classe et qu’elle est explicitement nommée. Par contre, si le hook a été inscrit sur une classe anonyme, cela pose un problème.
En cadeau donc un code qui permet de désinscrire un hook et qui fonctionne à tous les coups :