Après l’affichage d’un encart « articles similaires » en bas de page, le titre affiché juste en dessous — censé revenir à l’article principal — correspond soudain au dernier article de l’encart plutôt qu’à l’article consulté. Ce symptôme, déroutant la première fois qu’il apparaît, a une cause quasi systématique : une boucle secondaire lancée via WP_Query sans réinitialisation des données globales ensuite.
Symptôme
Le contenu affiché après une boucle personnalisée — titre, extrait, image à la une, lien permanent — correspond au dernier élément parcouru dans cette boucle, et non à l’article principal de la page. Le problème se manifeste uniquement à l’endroit précis où le code suit la boucle secondaire ; tout ce qui précède reste correct.
Diagnostic
WordPress maintient une variable globale $post, mise à jour à chaque itération de the_post() pendant une boucle. Une boucle secondaire construite avec une nouvelle instance de WP_Query, appelée depuis un template déjà en train d’afficher la boucle principale, modifie cette même variable globale au fil de ses propres itérations.

$articles_similaires = new WP_Query( array(
'category__in' => wp_get_post_categories( get_the_ID() ),
'posts_per_page' => 3,
'post__not_in' => array( get_the_ID() ),
) );
if ( $articles_similaires->have_posts() ) :
while ( $articles_similaires->have_posts() ) : $articles_similaires->the_post();
the_title();
endwhile;
endif;
// Ici, $post pointe encore vers le dernier article
// de la boucle secondaire, pas vers l'article principal.
the_title();
Sans instruction spécifique après la boucle, la variable globale $post reste sur sa dernière valeur, celle du dernier article de l’encart « similaires », et toute fonction utilisant les données globales de l’article affiche des informations erronées.
Correctif
if ( $articles_similaires->have_posts() ) :
while ( $articles_similaires->have_posts() ) : $articles_similaires->the_post();
the_title();
endwhile;
wp_reset_postdata();
endif;
the_title(); // Affiche de nouveau le bon article.
wp_reset_postdata() restaure la variable globale $post à partir de la requête principale de la page, celle stockée dans $GLOBALS['wp_query']. Un seul appel, placé juste après la fin de la boucle secondaire, suffit à corriger l’ensemble du symptôme.
Prévention
- Toute boucle construite avec une nouvelle instance de
WP_Query, dès qu’elle appellethe_post(), doit se terminer par unwp_reset_postdata(), sans exception. - Une astuce de relecture de code : chercher systématiquement chaque
new WP_Query(dans un thème et vérifier qu’unwp_reset_postdata()lui correspond bien un peu plus loin. - Une boucle construite avec
pre_get_postssur la requête principale, elle, ne nécessite aucune réinitialisation : elle ne crée pas de nouvelle instance deWP_Query.
Un piège voisin : query_posts
La fonction query_posts(), plus ancienne, modifie directement la requête principale de la page plutôt que d’en créer une nouvelle, ce qui rend son usage encore plus risqué et déconseillé par la documentation officielle elle-même au profit de pre_get_posts ou d’une instance dédiée de WP_Query.
Un repère fiable en revue de code : aucune boucle secondaire ne devrait jamais rester sans son
wp_reset_postdata()associé, même si le symptôme n’apparaît pas immédiatement visible sur la page en cours de test.
En résumé
Ce bug classique se reconnaît à un symptôme très localisé : tout ce qui suit une boucle secondaire affiche les données du mauvais article. Le correctif ne demande qu’une ligne, mais encore faut-il penser à la placer systématiquement, dès l’écriture de la boucle et non après avoir constaté le problème en production.