WordPress の固定ページで「次のページ」「前のページ」ナビゲーションを表示する

WordPress の固定ページを使って、例えば次のような階層化されたサイトを作りたいとします。

WordPressの階層化されたページの例

この時、よくあるCMSのように、以下のようなナビゲーションが欲しくなります。

  • 同じ親ページを持つページ同士で「前のページ」「次のページ」のリンク
  • 親ページへ上がるリンク

イメージとしてはこんな感じ。読み物系のサイト(?)で良く見掛けるやつです。

WordPressのページナビゲーション例

固定ページではなく「投稿」であれば、previous_post_link() や next_post_link() で「前のページ」「次のページ」へのリンクを取得出来るのですが、固定ページで上記の条件を満たすものを取得しようとすると、ちょっとコードを書かないといけません。

データベース(wp_postsテーブル)から必要な情報を取得

WordPressの記事は wp_posts というテーブルに保存されていますが、このテーブルから必要な情報を取得します。必要になるのは、次のカラムです。

  • post_parent: 親ページのID
  • menu_order: 同じ階層のページでの順序

ちなみに、管理画面の「固定ページ」との対応は、下の図の通りです。

WordPress管理画面とDBカラム

実際の処理

次に、データベースから取得した情報を使って実際の処理を行ないます。実際の処理のアルゴリズムはこんな感じでしょう。

  1. まず、現在表示中のページの親ページを取得する
  2. 親ページが存在するなら、現在表示中のページの「順序」(menu_order)を取得する
  3. 親ページが同じで、現在表示中のページと「順序」が隣り合ったページを取得すると、それが「前のページ」と「次のページ」になる。

これをコードで書くと、下のような感じになります。なお、固定ページなので、WordPressテーマの page.php に書きます。

<?php 
...(ヘッダの表示など。省略)...

while (have_posts()) : the_post(); // 繰り返し処理開始 ?>

...(タイトルや本文の表示など。省略)...

<div class="navigation">
<?php 
// 親ページを取得
$parent = $post->post_parent;

if ( $parent ) {
    // 現在表示しているページの順番を取得
    $menu_order = $post->menu_order;

    // 前のページ
    $prev_post = $wpdb->get_row("SELECT * FROM wp_posts
        WHERE post_parent = $parent
            AND post_status = 'publish'
            AND menu_order < $menu_order
        ORDER BY menu_order DESC");
    if( $prev_post ): ?>
  <div class="prev">
    <a href="<?php echo get_page_link($prev_post->ID); ?>">
      ←
      <?php echo $prev_post->post_title; ?>
    </a>
  </div>
    <?php 
endif;
    ?>
    <?php // 親ページ ?>
    <div class="up">
      <a href="<?php echo get_page_link($parent); ?>">
        ↑
        <?php echo $wpdb->get_var("SELECT post_title FROM wp_posts WHERE ID = $parent"); ?>
      </a>
    </div>
    <?php
    // 次のページ
    $next_post = $wpdb->get_row("SELECT * FROM wp_posts
        WHERE post_parent = $parent
            AND post_status = 'publish'
            AND menu_order > $menu_order
        ORDER BY menu_order");
    if( $next_post ): ?>
  <div class="next">
    <a href="<?php echo get_page_link($next_post->ID); ?>">
      →
      <?php echo $next_post->post_title; ?>
    </a>
  </div>
    <?php 
endif; 
}
?> 
</div>
<!-- /post navigation -->

...(フッタの表示など。省略)...

ヘッダやフッタ、本文の表示などは省略してあります。あと、「前のページ」と「次のページ」を取得するSQLがほぼ同じなので、本当はもうちょっとうまくまとめるべきだと思います(^^;

[追記(12/3)]

サンプルコードを2点修正しました。

  1. 「前のページ」を取得するSQLで、”ORDER BY menu_order” を “ORDER BY menu_order DESC” に変更。こうしないと、「前のページ」が常に先頭ページになってしまう。
  2. 「前のページ」「次のページ」のリンクを表示するのに、previous_post_link(), next_post_link() ではなく get_page_link() を使用。
スポンサーリンク
スポンサーリンク:

フォローする