En développant une extension de réservation pour des chambres d’hôtes, destinée à être réutilisée sur plusieurs sites d’une même agence, j’ai vite réalisé qu’un intégrateur freelance ne travaillerait jamais sur mon code source directement. Chaque site avait ses spécificités visuelles et métier. La question qu’il m’a posée, presque en passant, a orienté toute l’architecture du plugin : « comment je modifie ce bout de HTML sans toucher à votre code ? »
La réponse tient dans la conception volontaire de points d’extension, avec do_action() et apply_filters(), pensés comme une véritable API interne plutôt que comme un ajout de dernière minute.
Repérer les bons endroits pour un hook
Toutes les lignes de code ne méritent pas un hook : en ajouter partout nuit à la lisibilité et complique la maintenance. Trois catégories de code se prêtent particulièrement bien à l’exposition d’un point d’extension.
- Une sortie HTML destinée à être personnalisée visuellement (avant, après, ou en remplacement complet d’un bloc)
- Une valeur calculée qui pourrait légitimement varier selon le contexte métier d’un site (un tarif, une durée, une capacité)
- Un moment clé du cycle de vie d’une donnée (avant sauvegarde, après confirmation, avant annulation)
Pour ce plugin de réservation, le calcul du tarif final s’est révélé être le point d’extension le plus demandé par les intégrateurs : chaque hôte pratiquait des règles de majoration différentes selon la saison, ce que le cœur du plugin ne pouvait pas anticiper.
Filtrer une valeur calculée avec apply_filters
function sejours_calculer_tarif_final( $tarif_base, $chambre_id, $dates ) {
$tarif = $tarif_base;
// logique interne au plugin, calcul de base
/**
* Filtre le tarif final d'une réservation avant affichage.
*
* @param float $tarif Tarif calculé par le plugin.
* @param int $chambre_id Identifiant de la chambre concernée.
* @param array $dates Tableau contenant 'arrivee' et 'depart'.
*/
return apply_filters( 'sejours_tarif_final', $tarif, $chambre_id, $dates );
}
Transmettre $chambre_id et $dates en plus du tarif, même si le filtre pourrait techniquement fonctionner avec la seule valeur numérique, permet à un développeur tiers d’appliquer une règle conditionnelle sans avoir à recharger ces informations depuis la base de données. C’est ce contexte additionnel qui transforme un filtre basique en véritable point d’extension exploitable.
Marquer un moment du cycle de vie avec do_action

function sejours_confirmer_reservation( $reservation_id ) {
update_post_meta( $reservation_id, '_sejours_statut', 'confirmee' );
/**
* Se déclenche juste après la confirmation d'une réservation.
*
* @param int $reservation_id Identifiant de la réservation confirmée.
*/
do_action( 'sejours_reservation_confirmee', $reservation_id );
}
Ce hook a permis à un intégrateur, sur un site particulier, de brancher l’envoi automatique d’un SMS de confirmation via un service tiers, sans qu’une seule ligne du plugin lui-même n’ait besoin d’être modifiée. C’est exactement l’objectif recherché : le cœur du plugin reste identique sur tous les sites, seule une extension légère et spécifique à chaque client vient se greffer dessus.
Nommer et préfixer sans ambiguïté
Un nom de hook générique comme calculer_tarif entrerait presque certainement en collision avec une autre extension installée sur le même site. La règle que j’applique systématiquement : préfixer chaque hook avec un identifiant court et unique du plugin, cohérent avec le préfixe déjà utilisé pour les fonctions et les options.
// À éviter : trop générique, risque de collision
apply_filters( 'calculer_tarif', $tarif );
// À privilégier : préfixé, explicite
apply_filters( 'sejours_tarif_final', $tarif, $chambre_id, $dates );
Ce même préfixe doit rester strictement identique partout dans le plugin, y compris dans les noms d’options, de tables et de classes. Un intégrateur qui explore le code source pour comprendre les points d’extension disponibles s’appuie largement sur cette cohérence pour naviguer rapidement.
Documenter les hooks pour de vrai
Un hook non documenté est, dans les faits, un hook qui n’existe pas pour la plupart des développeurs tiers pressés. Le bloc de commentaire PHPDoc placé juste avant chaque do_action ou apply_filters, comme dans les exemples précédents, constitue un minimum. Pour ce plugin, distribué à plusieurs agences partenaires, j’ai complété cette documentation en code par une liste centralisée dans un fichier HOOKS.md à la racine, recensant chaque hook avec sa description, ses arguments et un exemple d’utilisation.
Un hook que vous n’osez pas documenter parce que son comportement est instable ou mal défini est probablement un hook qui n’est pas encore prêt à être exposé publiquement.
En résumé
Concevoir ses propres hooks demande d’anticiper, dès l’architecture initiale, les endroits où une personnalisation légitime sera nécessaire sans passer par une modification du code source. Ce travail se fait en amont, rarement à la demande, et c’est justement ce qui distingue une extension pensée pour être étendue d’une extension qui se contente de fonctionner isolément.