2026年5月29日
2026年5月29日
WordPressの前後の記事リンク(前の投稿・次の投稿)を制御する方法
WordPressの「前の投稿・次の投稿」リンクは、クラシックテーマなら the_post_navigation() や previous_post_link() / next_post_link() の引数で、ブロックテーマなら「投稿ナビゲーションリンク」ブロックの設定で制御できます。この記事では、同じカテゴリー内だけで移動させる、特定カテゴリーを飛ばす、表示文言やサムネイル付きの見た目に変える、といったよくある要望を、子テーマの functions.php やテンプレートの書き換えで実現する手順を解説します。
前後の記事リンクの仕組みを先に押さえる
前後リンクの対象は、表示中の投稿と同じ投稿タイプの公開済み記事のうち、公開日時がひとつ古いもの(前の投稿)とひとつ新しいもの(次の投稿)です。並び順は公開日時が基準で、メニュー順やカスタムフィールドの値では決まりません。
コアの関数は次の関係になっています。
get_previous_post()/get_next_post():隣の投稿オブジェクトを取得するだけで、HTMLは出力しないprevious_post_link()/next_post_link():リンクを1本ずつ出力するthe_post_navigation():前後のリンクを<nav>で囲んでまとめて出力する
どれも内部では同じ「隣接投稿」の検索処理を使うため、カテゴリーの絞り込みや除外の考え方は共通です。テーマがどの関数を使っているかは、テーマの single.php(または template-parts 内のファイル)を開き、関数名で検索すると分かります。
作業前に、子テーマが用意されているかを確認してください。親テーマの single.php を直接書き換えると、テーマ更新で変更が消えます。子テーマに single.php をコピーし、そちらを編集するのが基本です。
クラシックテーマで同じカテゴリー内に限定する
the_post_navigation() は配列で引数を受け取ります。in_same_term を true にすると、表示中の記事と同じタームを持つ記事だけが前後リンクの対象になります。
<?php
the_post_navigation(
array(
'prev_text' => '<span class="nav-label">' . esc_html__( '前の記事', 'my-child-theme' ) . '</span> %title',
'next_text' => '<span class="nav-label">' . esc_html__( '次の記事', 'my-child-theme' ) . '</span> %title',
'in_same_term' => true,
'taxonomy' => 'category',
)
);
%title は隣の記事のタイトルに置き換わります。自分で書く文言は esc_html__() などでエスケープしておくと、翻訳ファイルを使う場合も安全です。
1本ずつ出力する関数を使っているテーマでは、引数の順番に注意してください。第1引数が書式、第2引数がリンク文字列、第3引数が同じタームに限定するか、第4引数が除外するタームID、第5引数がタクソノミーです。
<?php
previous_post_link( '%link', '« %title', true, '', 'category' );
next_post_link( '%link', '%title »', true, '', 'category' );
ひとつの記事に複数のカテゴリーが付いている場合、「同じターム」はそのどれかと共通していれば対象になります。カテゴリーをまたいで移動しているように見えるときは、記事に付いているカテゴリーを見直してください。
カスタム投稿タイプとカスタムタクソノミーの場合
カスタム投稿タイプでも同じ関数が使えますが、標準の taxonomy は category です。独自タクソノミー(例:genre)で絞り込みたいときは、'taxonomy' => 'genre' のように明示します。指定し忘れると、カテゴリーを持たない投稿タイプでは前後リンクが出なくなることがあります。
特定のカテゴリーを前後リンクから外す
お知らせ用カテゴリーなど、前後リンクに混ぜたくない記事群がある場合は excluded_terms にタームIDを指定します。タームIDは管理画面の「投稿」→「カテゴリー」で編集画面を開いたとき、URLの tag_ID= の値で確認できます。
<?php
the_post_navigation(
array(
'excluded_terms' => array( 12, 15 ), // 除外するカテゴリーのID
'taxonomy' => 'category',
)
);
テンプレートを触らずに、サイト全体でまとめて除外したいときはフィルターを使う方法もあります。get_previous_post_excluded_terms と get_next_post_excluded_terms は、除外するタームIDの配列を受け取って返すフィルターです。
<?php
// 子テーマの functions.php
function mytheme_adjacent_excluded_terms( $excluded_terms ) {
$excluded_terms = is_array( $excluded_terms ) ? $excluded_terms : array();
$excluded_terms[] = 12; // お知らせカテゴリーのID
return array_map( 'intval', array_unique( $excluded_terms ) );
}
add_filter( 'get_previous_post_excluded_terms', 'mytheme_adjacent_excluded_terms' );
add_filter( 'get_next_post_excluded_terms', 'mytheme_adjacent_excluded_terms' );
除外は「その記事をリンク先にしない」という意味で、除外カテゴリーの記事を表示しているときに前後リンク自体を消す処理ではありません。お知らせ記事ではナビゲーションを出したくない場合は、テンプレート側で if ( ! in_category( 12 ) ) のような条件分岐を入れます。
文言・HTMLを変えてサムネイル付きにする
タイトルだけのリンクでは物足りない場合は、get_previous_post() で投稿オブジェクトを取得し、HTMLを自分で組み立てます。隣の記事が無いときは空文字や null が返るため、WP_Post かどうかを判定してから使います。
<?php
$prev_post = get_previous_post( true, '', 'category' );
$next_post = get_next_post( true, '', 'category' );
?>
<nav class="my-post-nav" aria-label="<?php echo esc_attr__( '前後の記事', 'my-child-theme' ); ?>">
<?php if ( $prev_post instanceof WP_Post ) : ?>
<a class="my-post-nav__prev" href="<?php echo esc_url( get_permalink( $prev_post ) ); ?>">
<?php echo get_the_post_thumbnail( $prev_post, 'thumbnail' ); ?>
<span><?php echo esc_html( get_the_title( $prev_post ) ); ?></span>
</a>
<?php endif; ?>
<?php if ( $next_post instanceof WP_Post ) : ?>
<a class="my-post-nav__next" href="<?php echo esc_url( get_permalink( $next_post ) ); ?>">
<?php echo get_the_post_thumbnail( $next_post, 'thumbnail' ); ?>
<span><?php echo esc_html( get_the_title( $next_post ) ); ?></span>
</a>
<?php endif; ?>
</nav>
URLは esc_url()、タイトルは esc_html() を通して出力します。get_the_post_thumbnail() はコアが属性をエスケープしたimgタグを返すので、そのまま出力して問題ありません。アイキャッチ画像が未設定の記事では空文字になるため、レイアウトが崩れないようCSS側で画像の有無に依存しない幅を決めておくと扱いやすくなります。
テンプレートを書き換えずに出力HTMLだけ少し変えたい場合は、previous_post_link / next_post_link フィルター(previous_post_link() などの出力結果を受け取るフィルター)で文字列を加工する方法もあります。ただし大きく構造を変えるならテンプレートを編集した方が保守しやすいです。
ブロックテーマでは「投稿ナビゲーションリンク」ブロックを使う
Twenty Twenty-Five などのブロックテーマでは、single.php ではなく「単一投稿」テンプレートの中に「投稿ナビゲーションリンク」ブロックが置かれています。「外観」→「エディター」→「テンプレート」から単一投稿のテンプレートを開き、ブロックを選択すると、右側の設定パネルで次のような項目を変更できます(2026年10月現在)。
- 前の投稿へのリンクか、次の投稿へのリンクか
- 投稿タイトルを表示するかどうか、ラベルの文言
- 矢印の種類
最近のバージョンでは、同じタクソノミーのタームを持つ記事に絞り込む設定も用意されています。設定項目名はバージョンによって表記が異なることがあるため、自分の環境のパネルで確認してください。テンプレートのコードエディターで見ると、次のようなブロックとして保存されています。
<!-- wp:post-navigation-link {"type":"previous","showTitle":true,"arrow":"arrow"} /-->
<!-- wp:post-navigation-link {"type":"next","showTitle":true,"arrow":"arrow"} /-->
このブロックも内部ではコアの前後リンク関数を使って出力されるため、前の章で紹介した get_previous_post_excluded_terms などのフィルターは、ブロックテーマでもカテゴリー除外に使えます。サイトエディターで変更したテンプレートはデータベースに保存されるので、テーマのファイルとは別に管理される点も覚えておくと混乱しません。
うまくいかないときの確認ポイント
前後リンクが表示されない、意図しない記事に飛ぶ、というときは次の順で確認します。
- 編集したファイルが実際に使われているか。子テーマが有効か、テンプレート階層で別ファイル(single-{投稿タイプ}.php など)が優先されていないかを見ます。
- 隣の記事が存在するか。同じカテゴリー内に限定した場合、そのカテゴリーの最古・最新の記事では片方が出ないのが正常です。
- 下書き・予約投稿・非公開記事は対象外です。公開日時が同じ記事が複数あると、順番が直感と合わないことがあります。
- キャッシュ系プラグインやサーバーキャッシュが古いHTMLを返していないか。変更後はキャッシュを削除して確認します。
functions.php を編集してサイトが真っ白になった場合は、FTPやファイルマネージャーで追記部分を元に戻すと復旧できます。編集前に元のファイルを手元に保存しておいてください。
まとめ
- 前後リンクは同じ投稿タイプの公開記事を公開日時順にたどる仕組みで、
the_post_navigation()、previous_post_link()/next_post_link()、get_previous_post()が同じ検索処理を共有しています。 - 同じカテゴリー内に限定するなら
in_same_term、特定カテゴリーを外すならexcluded_terms、独自タクソノミーならtaxonomyを指定します。 - サイト全体で除外したい場合は
get_previous_post_excluded_terms/get_next_post_excluded_termsフィルターが使え、ブロックテーマにも効きます。 - 見た目を大きく変えるなら
get_previous_post()で投稿を取得し、esc_url()やesc_html()でエスケープしながらHTMLを組み立てます。 - ブロックテーマでは単一投稿テンプレートの「投稿ナビゲーションリンク」ブロックの設定で調整します。