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

Astuces

transition_post_status : éviter de dupliquer une alerte à chaque sauvegarde

save_post se déclenche à chaque enregistrement, même sans changement de statut réel. transition_post_status ne réagit qu'aux vraies bascules d'état.

Par WordPress Développement • 6 septembre 2023 • 4 min de lecture • Aucun commentaire
transition_post_status : éviter de dupliquer une alerte à chaque sauvegarde

Une alerte e-mail part trois fois pour la publication d’un seul article. Ce symptôme, un développeur WordPress finit toujours par le croiser, généralement en branchant une notification sur le hook save_post, qui semble pourtant le candidat naturel pour ce genre de besoin.

Le problème vient du fonctionnement même de save_post : ce hook se déclenche à chaque enregistrement d’un contenu, y compris lors des sauvegardes automatiques de brouillon, des révisions créées en arrière-plan, et de tout enregistrement qui ne correspond pas nécessairement à une bascule réelle de statut éditorial.

Ce que save_post ne distingue pas

Rien dans les arguments transmis à save_post n’indique directement si le statut du contenu vient de changer. Le développeur doit alors comparer manuellement l’ancien et le nouveau statut, en gérant lui-même les cas de révisions automatiques, de type de contenu à exclure, et de sauvegardes répétées liées à l’éditeur de blocs qui enregistre régulièrement en arrière-plan pendant la rédaction.

Cette logique de comparaison, réécrite à la main dans chaque fonction accrochée à save_post, devient vite source d’erreurs, avec des conditions oubliées qui déclenchent des doublons ou, à l’inverse, ratent une vraie transition.

transition_post_status : un hook dédié à la comparaison

L'essentiel à retenir : save_post se déclenche à chaque sauvegarde, y compris les révisions automatiques ; transition_post_status ne réagit qu'à un vrai changement de statut ; Il fournit directement l'ancien et le nouveau statut en paramètres

WordPress propose un hook spécifiquement conçu pour ce besoin : transition_post_status. Il se déclenche à chaque changement d’état d’un contenu, avec trois arguments directement exploitables : le nouveau statut, l’ancien statut, et l’objet WP_Post concerné.

add_action( 'transition_post_status', function ( $nouveau_statut, $ancien_statut, $post ) {
    if ( 'article' !== $post->post_type ) {
        return;
    }

    if ( 'publish' === $nouveau_statut && 'publish' !== $ancien_statut ) {
        wp_mail(
            'redaction@example.com',
            'Nouvel article publié',
            sprintf( "L'article « %s » vient de passer en ligne.", $post->post_title )
        );
    }
}, 10, 3 );

La condition 'publish' !== $ancien_statut est ici essentielle : elle garantit que l’alerte ne part qu’au moment précis où l’article bascule vers l’état publié, pas à chaque enregistrement ultérieur d’un article déjà en ligne.

Pourquoi trois arguments changent tout

La grande force de ce hook tient à ce qu’il fournit à la fois l’ancien et le nouveau statut dans un seul appel, sans avoir à interroger la base de données pour retrouver l’état précédent. Cela permet de couvrir des transitions bien plus fines qu’un simple passage en « publié » :

  • D’un statut draft vers pending, pour notifier un relecteur qu’un contenu attend sa validation.
  • D’un statut publish vers trash, pour tracer la mise à la corbeille d’un contenu sensible.
  • D’un statut personnalisé vers un autre, sur un flux éditorial qui définit ses propres statuts via register_post_status().

Un exemple avec des statuts personnalisés

Sur un projet qui gère un flux de relecture à plusieurs niveaux, un statut personnalisé en_relecture peut être déclaré, puis surveillé exactement de la même façon :

register_post_status( 'en_relecture', array(
    'label'                     => 'En relecture',
    'public'                    => false,
    'internal'                  => true,
    'exclude_from_search'       => true,
    'show_in_admin_all_list'    => true,
    'show_in_admin_status_list' => true,
) );

add_action( 'transition_post_status', function ( $nouveau, $ancien, $post ) {
    if ( 'en_relecture' === $nouveau && 'en_relecture' !== $ancien ) {
        // Notifier l'équipe de relecture désignée.
    }
}, 10, 3 );

La différence avec wp_after_insert_post

Un hook plus récent, wp_after_insert_post, couvre un besoin voisin mais distinct : il se déclenche une fois qu’un contenu et toutes ses métadonnées associées ont fini d’être enregistrés, ce qui le rend plus adapté quand la logique dépend de champs personnalisés déjà à jour. transition_post_status, lui, reste focalisé sur la seule question du changement d’état, sans attendre la fin complète du processus d’enregistrement.

Sur toute notification liée à un changement d’état éditorial, comparer explicitement l’ancien et le nouveau statut évite de renvoyer la même alerte à chaque clic sur « Mettre à jour », un piège que beaucoup découvrent seulement après plusieurs plaintes de la rédaction.

En résumé

Le bon réflexe consiste à se poser la question : ce déclenchement dépend-il réellement d’un changement de statut ? Si la réponse est oui, transition_post_status évite d’écrire à la main une comparaison qui existe déjà nativement, et referme du même coup la porte aux doublons de notification qui agacent tant les équipes éditoriales.

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