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

Astuces

wp_after_insert_post : agir seulement quand un article est vraiment publié

Le hook save_post se déclenche trop tôt et trop souvent. Voici comment utiliser wp_after_insert_post pour réagir une fois l'article réellement enregistré, avec ses métadonnées et ses termes.

Par WordPress Développement • 6 juillet 2023 • 5 min de lecture • Aucun commentaire
wp_after_insert_post : agir seulement quand un article est vraiment publié

La documentation du Trac de WordPress décrit wp_after_insert_post ainsi : « Fires once a post, its terms and meta have been saved. » Cette phrase, en apparence anodine, résout un problème que beaucoup de développeurs rencontrent sans le nommer précisément : le hook save_post se déclenche avant que tout ne soit vraiment en place.

Concrètement, si vous accrochez une notification, un appel à une API externe ou une génération de PDF sur save_post, il n’est pas rare que les champs personnalisés associés à l’article ne soient pas encore enregistrés au moment où votre code s’exécute, ou que les termes de taxonomie ne soient pas encore assignés. Le résultat : des emails incomplets, des exports vides, des webhooks envoyés avec des données partielles.

Le problème concret avec save_post

save_post se déclenche à l’intérieur de wp_insert_post(), à un moment où le post est enregistré en base mais où certaines opérations liées (comme l’enregistrement des métadonnées via des blocs personnalisés, ou l’attribution de termes différée par d’autres extensions) peuvent encore être en cours. Ce hook se déclenche aussi plusieurs fois dans certains scénarios : une fois pour l’enregistrement de brouillon automatique, une fois pour chaque révision, une fois pour la publication finale. Sans précaution, un même traitement peut se répéter inutilement plusieurs fois de suite.

Ce que change wp_after_insert_post

Introduit dans WordPress 5.6, ce hook se déclenche une seule fois, à la toute fin de wp_insert_post(), après que les métadonnées ont été enregistrées et que les termes ont été assignés. Sa signature transmet quatre arguments : l’identifiant du post, l’objet WP_Post à jour, un booléen indiquant s’il s’agit d’une mise à jour, et l’objet WP_Post tel qu’il était avant la modification. Ce dernier paramètre est particulièrement utile pour comparer un ancien et un nouveau statut sans requête supplémentaire.

L'essentiel à retenir : wp_after_insert_post s'exécute après les métadonnées et les termes ; Il ne se déclenche qu'une seule fois par enregistrement ; Idéal pour les traitements qui dépendent de données complètes

Mettre en place un déclenchement propre

Voici comment ne réagir que lorsqu’un article passe réellement au statut publié, en comparant l’état avant et après :

add_action( 'wp_after_insert_post', 'wpm_notifier_publication_finalisee', 10, 4 );

function wpm_notifier_publication_finalisee( $post_id, $post, $update, $post_before ) {
    if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
        return;
    }

    $etait_publie = $post_before && 'publish' === $post_before->post_status;
    $est_publie   = 'publish' === $post->post_status;

    if ( $est_publie && ! $etait_publie ) {
        // Ici, les métadonnées et les termes sont déjà enregistrés.
        $categories = wp_get_post_terms( $post_id, 'category', array( 'fields' => 'names' ) );
        $auteur     = get_the_author_meta( 'display_name', $post->post_author );

        // Traitement fiable : email, appel API, écriture de log...
    }
}

Ce filtre de garde en début de fonction évite les répétitions liées aux révisions automatiques, un piège fréquent avec save_post que ce nouveau hook ne résout pas automatiquement : il ne filtre pas les révisions à votre place, il faut le faire soi-même.

Pourquoi comparer post_before et post

Sans cette comparaison, chaque mise à jour ultérieure de l’article (correction de coquille, ajout d’un paragraphe) redéclencherait le même traitement puisque le statut resterait « publish » des deux côtés — mais la condition $est_publie && ! $etait_publie devient alors fausse, ce qui bloque bien les répétitions inutiles.

Variante : limiter à un type de contenu précis

Pour un site qui gère plusieurs types de contenus (articles, pages, produits), il est courant de vouloir ne réagir que sur un post type donné :

  • Ajouter une vérification if ( 'post' !== $post->post_type ) { return; } en tout début de fonction.
  • Utiliser get_post_type( $post_id ) si vous préférez ne pas dépendre de l’objet transmis.
  • Combiner avec transition_post_status si vous avez besoin de connaître l’ancien statut avant même que les métadonnées ne soient sauvegardées, au prix de perdre la garantie de complétude des données.

Règle maison : si votre traitement lit des champs personnalisés ou des termes de taxonomie, préférez toujours wp_after_insert_post à save_post. Le gain en fiabilité dépasse largement le coût d’apprentissage d’un hook de plus.

Ce que ce hook ne remplace pas

Il ne remplace pas transition_post_status lorsque vous avez besoin d’agir avant l’enregistrement définitif, ni publish_post qui reste pertinent pour des cas simples sans dépendance aux métadonnées. Il ne convient pas non plus si votre logique doit s’exécuter de façon synchrone avant que l’utilisateur ne voie la confirmation d’enregistrement dans l’éditeur : dans ce cas, un traitement asynchrone via une tâche planifiée reste préférable pour ne pas ralentir l’interface.

En résumé

Le hook wp_after_insert_post comble un vide réel entre save_post, trop précoce, et publish_post, trop spécifique. Il garantit que les métadonnées et les termes sont disponibles, à condition de filtrer soi-même les révisions et les autosaves, et de comparer l’état avant et après pour éviter les déclenchements en doublon. Une fois ce réflexe acquis, la fiabilité des traitements déclenchés à la publication s’en trouve nettement améliorée, sans plugin supplémentaire.

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