Skip to Content

Chapitre 5.2 — Hooks : actions & filtres

⏱️ TL;DR — Les hooks sont le mécanisme d’extension de WordPress, et le concept le plus important de tout le cours. Deux types : les actions (« à ce moment, fais quelque chose » — on exécute du code) et les filtres (« avant d’utiliser cette valeur, laisse-moi la modifier » — on transforme une donnée et on la retourne). Vous vous attachez à un hook avec add_action() / add_filter(). Le cœur, les thèmes et les plugins déclenchent des hooks (do_action() / apply_filters()) à des points clés. Maîtriser ce système, c’est pouvoir tout étendre sans jamais toucher au cœur.

🎯 Objectifs

  • Distinguer action et filtre et savoir quand utiliser lequel.
  • Écrire add_action / add_filter avec priorité et nombre d’arguments.
  • Comprendre do_action / apply_filters (déclencher ses propres hooks).
  • Éviter les pièges classiques (filtre qui ne retourne rien, priorité, retrait de hook).

1. L’idée : un système de publication/abonnement

WordPress, en s’exécutant, annonce des moments (« je suis à l’init », « je vais afficher le titre », « j’enregistre un article »). Votre code s’abonne à ces annonces pour réagir. C’est un patron observateur / événementiel.

💡 Pour un dev React — Les actions sont des event listeners : on('init', callback) → on réagit à un événement, sans valeur de retour. Les filtres sont des middlewares de transformation : value = filters.reduce((v, fn) => fn(v), initial) → chaque abonné reçoit la valeur, la transforme, et retourne la nouvelle. Toute la personnalisation de WordPress passe par ces deux primitives. Si vous ne devez retenir qu’une chose du cours : action = faire, filtre = transformer-et-retourner.


2. Les actions : faire quelque chose à un moment

Une action exécute du code à un point donné. Aucune valeur retournée.

// S'abonner : « quand WordPress arrive à init, exécute ma fonction » add_action( 'init', 'mon_prefixe_demarrer' ); function mon_prefixe_demarrer() { // enregistrer un CPT, un shortcode, etc. }

Le cœur déclenche l’action ainsi (vous ferez pareil dans vos plugins) :

do_action( 'init' ); // « j'y suis » → tous les callbacks abonnés s'exécutent

Exemples d’actions du cœur : init, wp_enqueue_scripts, save_post (un article vient d’être enregistré), admin_menu, wp_footer.


3. Les filtres : transformer une donnée

Un filtre reçoit une valeur, la modifie, et doit la retourner.

// « avant d'afficher le titre, laisse-moi le modifier » add_filter( 'the_title', 'mon_prefixe_suffixe_titre' ); function mon_prefixe_suffixe_titre( $title ) { return $title . ' ✨'; // ⚠️ TOUJOURS retourner la valeur }

Le cœur applique le filtre ainsi :

$title = apply_filters( 'the_title', $title ); // la valeur passe par tous les callbacks

Exemples de filtres du cœur : the_title, the_content, body_class, wp_nav_menu_items, pre_get_posts (technique : modifie l’objet query), rest_prepare_post (Partie 9).

⚠️ Piège n°1 — un filtre qui ne retourne rien. Oublier le return dans un filtre écrase la valeur par null : le titre disparaît, le contenu devient vide. Un filtre retourne TOUJOURS (au minimum la valeur reçue inchangée). C’est l’erreur la plus fréquente du débutant.


4. Priorité et nombre d’arguments

add_action/add_filter acceptent deux paramètres supplémentaires :

add_filter( 'the_content', 'mon_cb', 20, 1 ); // hook callback ^^ ^ // priorité --´ `-- nombre d'arguments passés au callback
  • Priorité (défaut 10) : ordre d’exécution. Plus petit = plus tôt. Deux callbacks à 10 s’exécutent dans l’ordre d’ajout ; un à 5 passe avant un à 20.
  • Nombre d’arguments (défaut 1) : combien d’arguments le hook transmet à votre callback. Si un hook fournit 3 infos et que vous en voulez 2, il faut le déclarer :
// save_post transmet ($post_id, $post, $update) add_action( 'save_post', 'mon_cb', 10, 3 ); function mon_cb( $post_id, $post, $update ) { /* … */ }

⚠️ Piège n°2 — l’argument manquant. Si votre callback attend $post mais que vous n’avez pas déclaré 3 (ou au moins 2) comme nombre d’arguments, WordPress ne vous passe que le premier → $post est null. Alignez toujours le 4ᵉ paramètre sur ce que votre fonction consomme.


5. Déclencher ses propres hooks (rendre son code extensible)

Vos plugins/thèmes peuvent exposer leurs propres hooks, pour que d’autres (ou vous-même plus tard) les étendent — c’est une marque de code pro :

// Dans votre plugin : offrir un point d'extension do_action( 'wpr_books_apres_import', $livre_id ); $prix = apply_filters( 'wpr_books_prix_affiche', $prix, $livre_id );

Ainsi, un autre développeur peut faire add_action('wpr_books_apres_import', …) sans modifier votre code. C’est exactement ce que fait WooCommerce (des centaines de hooks) pour être si extensible (Partie 10).


6. Retirer, vérifier, contexte

remove_action( 'wp_head', 'wp_generator' ); // retirer un callback du cœur remove_filter( 'the_content', 'wpautop' ); // idem pour un filtre has_action( 'init', 'mon_cb' ); // vérifier current_action(); doing_action('init'); // introspection

Pour retirer un hook, il faut le même nom de callback et la même priorité que lors de l’ajout — d’où l’intérêt de fonctions nommées (plutôt que des closures anonymes, difficiles à retirer).

⚠️ Piège n°3 — la closure impossible à retirer. add_action('init', function(){ … }); fonctionne, mais est impossible à remove_action (pas de référence nommée). Pour du code que d’autres pourraient devoir désactiver, préférez une fonction nommée ou une méthode de classe avec une référence stable.


7. Où placer ses hooks

  • Dans un plugin (Partie 7) ou le functions.php du thème (Partie 6), chargés au bootstrap (ch. 5.1).
  • On enregistre les hooks au chargement (pas dans une condition tardive) ; le callback, lui, s’exécutera au bon moment.
  • Bonne pratique : préfixer ses fonctions (monprefixe_…) pour éviter les collisions de noms dans l’espace global de PHP (pas de namespaces imposés par WordPress, Partie 7).

✏️ Exercices

  1. Vous voulez ajouter « (Lecture : 3 min) » à la fin du contenu de chaque article. Action ou filtre ? Sur quel hook ? Écrivez le squelette.
  2. Vous voulez envoyer un e-mail à chaque publication d’article. Action ou filtre ? Quel hook ?
  3. Un développeur se plaint que le titre de ses articles est devenu vide après avoir ajouté un filtre the_title. Quelle est la cause la plus probable ?

✅ Solution

  1. Filtre (on transforme une valeur, le contenu) sur the_content :
add_filter( 'the_content', 'monprefixe_temps_lecture' ); function monprefixe_temps_lecture( $content ) { return $content . '<p><em>Lecture : 3 min</em></p>'; // retourne la valeur modifiée }
  1. Action (on fait quelque chose, envoyer un mail, sans transformer de valeur) sur save_post (ou publish_post/transition_post_status pour cibler la publication).
  2. Le filtre ne retourne pas la valeur (return oublié) → le titre est écrasé par null. Un filtre doit toujours retourner (au moins la valeur reçue).

🧠 Quiz de révision

1. Différence entre une action et un filtre ?

Une action exécute du code à un moment (sans retour) ; un filtre reçoit une valeur, la modifie et la retourne.

2. Comment s’abonne-t-on à un hook ?

Avec add_action( $hook, $callback, $priorite, $nb_args ) ou add_filter( … ).

3. Que signifie une priorité de 5 vs 20 ?

Plus petit = plus tôt : la priorité 5 s’exécute avant la 20 (défaut : 10).

4. Que se passe-t-il si un filtre ne retourne rien ?

Il écrase la valeur par null (contenu/titre vide) : un filtre doit toujours retourner.

5. Comment rendre son propre plugin extensible ?

En déclenchant ses propres hooks avec do_action() / apply_filters() aux points clés.


Chapitre suivant : La Boucle (The Loop).