本文へ移動

トラブル解決

関連記事の追加後に記事タイトル・本文が別の記事へ変わる原因
|wp_reset_postdata()を確認

個別記事へ関連記事や新着記事の一覧を追加したあと、開いている記事のURLはそのままなのに、タイトルや本文だけが一覧の最後の記事へ変わっていませんか。実際の再現画面を見ながら、原因を確認する値と修正位置を順番に整理します。

Huddly Huddly 投稿日: 2026年10月9日 読了目安: 6分

関連記事の処理後だけ表示が変わるならリセットを確認する

個別記事に関連記事や新着記事の一覧を追加したあと、その一覧より後で表示するタイトルや本文だけが最後の関連記事へ変わるなら、まずwp_reset_postdata()の戻し忘れを確認します。サブループの直後でglobal $postを、いまブラウザで開いている記事へ戻します。

どこから別の記事へ変わるかを先に確認する

この記事でいうサブループは、ブラウザで開いている個別記事とは別に、関連記事や新着記事などを取得して表示する追加のループです。本文の下だけでなく、上部、サイドバー、テンプレートパーツ内に置く場合もあります。大切なのは画面上の上下ではなく、PHPが実行される順番です。

サブループの作り方や、1ページで複数の一覧を安全に扱う基本は、次の記事で詳しく説明しています。

この記事では、ブラウザで開いている記事を「WordPress高速化ガイド」(ID 28)、追加する関連記事を「関連記事:キャッシュの使い方」(ID 26)と「関連記事:画像を軽くする方法」(ID 27)として再現します。関連記事は正しく表示されますが、その処理の後に実行されるthe_title()やthe_content()が、最後の関連記事のタイトルや本文を表示してしまう状態です。

画面で起きること考えやすい原因最初の確認
関連記事・新着記事の一覧は正しいが、その処理より後のタイトル・本文が一覧の最後の記事になるサブループのglobal $postが残っているループ直後のwp_reset_postdata()
サブループの中ですでにタイトル・本文がずれているthe_post()の呼び忘れ・位置違いhave_posts()とthe_post()の順番
追加一覧に出る投稿そのものが違うWP_Queryの条件が目的と違う$argsと取得した投稿ID
PHPエラーが出ず、ページのURLも変わらないのに、タイトルや本文だけが別の記事へ変わるのが特徴です。

追加した一覧の最後の記事と同じタイトル、本文、アイキャッチ、リンク先URLが、その処理の後にも表示されているなら、取得条件を変える前に投稿データの参照先を調べます。

次の画面は、検証用WordPressで動かした記事ページです。上部のタイトルと「あわせて読みたい」は正しいままですが、赤枠の「この記事のまとめ」だけが最後の関連記事へ変わっています。まとめには投稿のタイトルと抜粋を表示しています。

WordPress高速化ガイドのサイト画面。ヘッダーと関連記事26・27はそのままで、赤枠のこの記事のまとめだけがID 27の画像を軽くする方法に変わっている
実際の不具合画面関連記事一覧のあとに、別記事のまとめが出る

赤枠にはID 28「WordPress高速化ガイド」のまとめが出るはずですが、リセットなしでは最後の関連記事、ID 27のタイトルと抜粋が表示されています。

追加した一覧に出ている記事そのものが間違っている場合は、wp_reset_postdata()では直りません。この関数が戻すのは取得条件ではなく、テンプレートタグが表示対象として使う投稿データです。

サブループの最後の記事を参照したままになる理由

独自クエリの$related_query->the_post()は、取得した一覧の次の記事へ進む処理です。それに加えて、「いまどの記事を表示しているか」を表すglobal $postも、その関連記事へ切り替えます。ここで使う->は、左側の$related_queryに対して右側のthe_post()を呼び出すPHPの書き方です。$related_queryは引数ではなく、操作する取得結果を持つWP_Queryオブジェクトを示しています。

the_title()、the_content()、get_the_ID()などは、投稿IDを明示しない場合、global $postに入っている記事を使います。今回の例では、ループの最後に「関連記事:画像を軽くする方法」が入ったままになるため、その後のテンプレートタグもこの関連記事を表示します。

一方、get_queried_object_id()は、WordPressが今開いているURLから判断した個別記事のIDを返します。そのため、URLが示すIDは「WordPress高速化ガイド」のままでも、global $postとget_the_ID()だけが最後の関連記事へずれることがあります。

確認する値リセットがないときの変化分かること
get_queried_object_id()開いている個別記事のIDのまま今開いているURLの対象は変わっていない
$post(global $postで参照)追加一覧の最後の記事になるテンプレートタグの表示対象が最後の関連記事のまま
get_the_ID()追加一覧の最後の記事になる$postに入っている記事のIDを返している
the_title()・the_content()追加一覧の最後の記事を表示する別のタイトル・本文として画面に現れる

whileの処理が終わっただけでは、global $postはブラウザで開いている個別記事へ戻りません。サブループを終えた位置で、投稿データを元へ戻す処理が必要です。

resetなしのコードではループ後も関連記事を参照する

次は、個別記事のテンプレートで関連記事を表示し、その処理の後に、開いている記事のタイトルと本文を表示する失敗例です。検証用のクラシックテーマのsingle.phpで、メインループのthe_post()を実行した後に置く部分を示します。実際のサイトで試すときは、既存のタイトル・本文の出力と二重にならない位置にしてください。

今回は画像と同じ2件だけを、ID 26、27の順に取得します。これらのIDは検証用の値なので、ご自身の検証環境にある2件の投稿IDへ置き換えます。関連記事の自動選定ではなく、同じ投稿を使って、リセットの有無だけを比べるための条件です。

クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。

PHPsingle.phpwp_reset_postdata()がない失敗例
$related_query = new WP_Query(   [      'post_type'           => 'post',      'post_status'         => 'publish',      'posts_per_page'      => 2,      'post__in'            => [ 26, 27 ],      'orderby'            => 'post__in',      'ignore_sticky_posts' => true,   ]); if ( $related_query->have_posts() ) {   echo '<ul>';    while ( $related_query->have_posts() ) {      $related_query->the_post();       printf(         '<li><a href="%1$s">%2$s</a></li>',         esc_url( get_permalink() ),         esc_html( get_the_title() )      );   }    echo '</ul>';} // ここでは global $post が最後の関連記事を指したままです。the_title( '<h2>', '</h2>' );the_content();

この状態では、最後の2行が、いま開いている「WordPress高速化ガイド」ではなく、サブループで最後に表示した「関連記事:画像を軽くする方法」のタイトルと本文を出します。post__not_inや並び順を変えても、ループ後の表示対象は元へ戻りません。

wp_reset_postdata()をサブループ直後へ置く

修正では、追加したループが終わった直後、次のタイトルや本文を出す前にwp_reset_postdata()を置きます。次の例では、関連記事を囲むifが閉じた後に1回だけ追加しています。

クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。

PHPsingle.phpサブループ直後に投稿データを戻す修正版
$related_query = new WP_Query(   [      'post_type'           => 'post',      'post_status'         => 'publish',      'posts_per_page'      => 2,      'post__in'            => [ 26, 27 ],      'orderby'            => 'post__in',      'ignore_sticky_posts' => true,   ]); if ( $related_query->have_posts() ) {   echo '<ul>';    while ( $related_query->have_posts() ) {      $related_query->the_post();       printf(         '<li><a href="%1$s">%2$s</a></li>',         esc_url( get_permalink() ),         esc_html( get_the_title() )      );   }    echo '</ul>';} wp_reset_postdata(); // ここからは、いま開いている個別記事を参照します。the_title( '<h2>', '</h2>' );the_content();

このコードのポイントは、関連記事のループが終わった直後にwp_reset_postdata()を1回呼ぶことです。メインクエリで表示対象になっている投稿を使って、global $postなどの投稿データを設定し直します。個別記事のメインループ内なら、通常はブラウザで開いている記事へ戻ります。

修正前と同じサイト画面で、緑枠のこの記事のまとめがID 28のWordPress高速化ガイドへ戻っている
修正後の実画面同じ条件で、ID 28の記事のまとめへ戻る

取得条件も関連記事も画面の配置も同じです。サブループ直後にwp_reset_postdata()を追加すると、緑枠にID 28「WordPress高速化ガイド」のタイトルと抜粋が戻ります。

ただし、wp_reset_postdata()は任意の直前の状態へ戻す関数ではありません。独自ループの中に別の独自ループを入れた場合は、外側のWP_Queryオブジェクトのreset_postdata()で戻す必要があります。まずは今回のように、個別記事へ関連記事を1つ追加した構成で動きを確かめます。

リセットを加えたコードは、本番とは分けたWordPress環境で、関連記事の後のタイトルと本文が元へ戻るか試します。検証や公開に使うサーバーをこれから用意する場合は、Xserverの料金・バックアップ条件も確認できます。契約によってリセット忘れが直るわけではありません。

サブループの直後に投稿データを戻す

リセットはページ末尾やfooter.phpへまとめず、サブループを書いたテンプレートやテンプレートパーツ内に置きます。サブループと元へ戻す処理を離すと、その間に追加されたテンプレートタグが別の記事を参照してしまうためです。

置く位置おすすめ度理由
独自WP_Queryのwhile終了直後おすすめその後の表示より前に、開いている個別記事へ戻せる
テンプレートパーツの呼び出し元避けるパーツの外まで別の記事を参照する状態が残る
ページ末尾やfooter.php遅すぎる途中のタイトル・本文はすでに別の記事へ変わる
ループの1件ごと不要次のthe_post()で再び切り替わり、処理の意図も分かりにくくなる

取得結果が0件なら、そのループではthe_post()が呼ばれず、投稿データも切り替わりません。ただし、ifの外にリセットを1回置く基本の書き方にしておくと、取得件数の変更や条件分岐の追加後も後片付けを忘れにくくなります。

正常なループ内の順番も見直したい場合は、the_post()の役割と基本構文を次の記事で確認できます。

4つの値を同じ場所で記録して原因を確かめる

表示だけで判断しにくい場合は、ローカル環境でサブループの直後とwp_reset_postdata()の直後に同じログを置きます。URLが示す個別記事のIDと、テンプレートタグが表示対象にしている記事のIDを分けて記録するのがポイントです。

原因を切り分けるための一時的な確認コードです。ローカルなどの検証環境だけで使い、確認後は削除してください。

PHPsingle.php開いている個別記事とテンプレートタグの参照先を比較する
global $post; error_log(   wp_json_encode(      [         'queried_object_id' => get_queried_object_id(),         'global_post_id'    => $post instanceof WP_Post ? $post->ID : null,         'get_the_ID'        => get_the_ID(),         'title'             => get_the_title(),      ],      JSON_UNESCAPED_UNICODE   ));

wp-config.phpでWP_DEBUGとWP_DEBUG_LOGを有効にしている場合、通常はWordPressのwp-content/debug.logで出力を確認できます。画面にログを出さないため、WP_DEBUG_DISPLAYはfalseにします。これらはローカルやステージング環境だけで一時的に使い、本番では有効にしないでください。

queried_object_idだけがブラウザで開いている個別記事で、残り3つが最後の関連記事なら、クエリ条件より先にwp_reset_postdata()の有無と位置を確認します。4つがすべて開いている記事へ戻れば、その後のthe_title()やthe_content()も同じ記事を参照できます。確認用ログは原因を特定したら削除してください。

get_queried_object_idはブラウザで開いている個別記事のまま、global postとget_the_IDはリセットなしで最後の関連記事、リセットありで開いている個別記事になる比較画面
実際の確認値URLの対象とテンプレートタグの表示対象を分けて比べる

リセットなしでもURLが示すID 28の個別記事は変わりません。変わっているのはglobal $postと、それを使うテンプレートタグの表示対象です。

リセットで直らないときは表示が変わる場所を見直す

別タイトルが出る問題でも、発生位置によって確認先は変わります。

表示が変わる場所・症状確認するもの次の対応
サブループの中ですでに別の記事になるthe_post()の有無と位置have_posts()の直後、表示前に同じクエリのthe_post()を置く
サブループより後だけ最後の記事になるwp_reset_postdata()ループ直後、その後の表示より前へ置く
get_queried_object_id()も想定外メインクエリ・テンプレート階層表示中のURLと使われているテンプレートを確認する
追加一覧の投稿IDが想定外$args・フックpost_type、除外条件、pre_get_postsなどを確認する

IDや投稿オブジェクトを明示してget_the_title( $post_id )やget_permalink( $post_id )を使い、the_post()もsetup_postdata()も呼んでいない処理は、global $postを切り替えません。その処理だけを理由にwp_reset_postdata()を追加する必要はありません。

query_posts()でメインクエリそのものを置き換えた場合は、wp_reset_query()まで含めて別に考えます。新しい独自一覧にはnew WP_Query()を使い、今回の症状へ不要な修正を混ぜないようにします。

投稿データを戻す仕組みやWP_Queryの基礎から確認したい場合は、次の記事もあわせてご覧ください。

リセットの位置を直しても、関連記事として取得される投稿が違う場合は、投稿タイプや絞り込み条件を見直します。WP Query Builderで必要な条件を整理できます。

関連記事の取得条件を整理する

取得件数や投稿IDなどを指定して$argsを作れます。生成した条件を使うときも、この記事で説明したループの順序とリセット処理を確認してください。

リセット前後で、タイトルと投稿IDがどう変わるか

最後に、記事の表示対象が切り替わる順番を追ってみましょう。「WordPress高速化ガイド」(ID 28)を開き、関連記事2件を表示する例では、次のように変わります。上の画面と同じローカルWordPressで取得した値です。

記録した場所global $post / get_the_ID()の対象get_queried_object_id()の対象the_title()の表示
サブループ前開いている個別記事開いている個別記事WordPress高速化ガイド
サブループ1件目1件目の関連記事開いている個別記事関連記事:キャッシュの使い方
サブループ2件目2件目の関連記事開いている個別記事関連記事:画像を軽くする方法
リセットなしのループ後2件目の関連記事開いている個別記事関連記事:画像を軽くする方法
wp_reset_postdata()後開いている個別記事開いている個別記事WordPress高速化ガイド

URLの対象は途中で変わりません。表示対象だけが関連記事へ進み、最後のリセットで「WordPress高速化ガイド」へ戻ります。自分のページで調べるときも、同じ場所でIDを比べると、どこからずれたかを追いやすくなります。

投稿データを戻す仕様を公式資料で確認する

wp_reset_postdata()の戻り先と、WP_Queryのthe_post()が投稿データを設定する範囲は、WordPress公式ドキュメントで確認できます。

WordPress公式

確認に使ったWordPress公式ドキュメント

元の記事へ戻ったことを確かめてから反映する

タイトルだけでなく、本文やリンク先も元の記事へ戻っているかを確認してください。調査のために追加したログは取り除き、変更前のファイルへ戻せる状態で本番へ反映しましょう。

別の記事タイトルが出るときの最終確認

  • 関連記事・新着記事の一覧に出る投稿IDは正しい
  • 症状がサブループより後だけに出ている
  • get_queried_object_id()、get_the_ID()、global $postを同じ場所で比べた
  • 各サブループの直後にwp_reset_postdata()を置いた
  • 修正後の表示を確認し、デバッグログを削除した
WP Query BuilderBuilderで条件を組み直す条件を選び、WP_Queryのコードを画面で作れます。Builderでクエリを作る

この記事を書いた人

Huddly

Web制作 / フロントエンドエンジニア

WordPressとフロントエンド実装で迷いやすい点を、公式情報と検証結果を分けながら、初学者にも追いやすい順序で整理しています。

この記事の検証情報

検証環境

WordPress
7.1.4
PHP
8.3.36
テーマ
wpq-media + DDEV
対象
カスタム投稿 / taxonomy / meta_query

更新履歴

  • 2026年10月9日 初回公開

この記事を活用する

あとで見返す・共有する

お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。

任意のご支援 役に立ったときだけ、活動を応援できます OFUSEはサイト・記事制作に使います。支援の有無で、読める内容や使える機能は変わりません。