この記事は年以上前に書かれたもので、内容が古かったり、セキュリティ上の問題等の理由でリンクが解除されている可能性があります。
WordPressは基本的にブログエンジンですが、カスタマイズ等でCMS化も可能になります。その際、固定ページのカスタマイズは多くの場合必須となります。その一環として親ページと子ページのナビゲーションの作り方をご紹介。
WordPressをCMSとして利用する際に親の固定ページと、その親に属する子ページ専用のナビゲーションを作ろう、というお話。WPでブログ以外のサイトを作ったことがある人なら鼻歌交じりで出来る事だと思うのでスルーして頂ければと思います。
と言うわけで僕と同じくらいのレベルのビギナー向けTipsになります。説明が下手なので図を描きました。
施工イメージ

こんなん。サイドカラムとかによくあるナビゲーションです。親ページAとその子ページ全てのリンクを、親子双方のページに共通で配置、仮に親ページBとその子ページがあとで増えても自動でナビゲーションが作られる。これをWordPressで作ります、というのが今日の内容です。
想定する仕様
改めて、仕様を想定します。
- ナビゲーションはサイドバーに配置。※ループの外になります
- 親ページと子ページに親ページのタイトル、サブタイトル、リンクを設置
- 親ページと子ページに子ページのタイトルとリンクをリスト表示
- 新しい親ページが増えても管理画面のみで増築可能にする
こんなイメージ。これで親ページ、その親ページに属する子ページにいるときはその親子ページ専用のナビゲーションが出来ますね。ただし、長くなるのでここでは孫ページは想定していません。
ではコードを見てみます。
親ページと子ページに親ページのタイトルとリンクを表示

まずは、親ページのタイトルとリンクを、親ページ、子ページの両方に表示出来るようにします。
親ページのタイトルを取得し、親子両ページに実装
<?php
$parents_title = get_the_title($post->post_parent);
echo $parents_title;
?>
普通にget_the_titleでタイトルを取得します。これで親ページのタイトルを取得できました。
続いて親ページのリンクです。
親ページのリンクを取得し、親子両ページに実装
<?php
$ancestor = array_pop( get_post_ancestors( $post->ID ) );
$permalink = get_permalink( $ancestor );
echo ($permalink);
?>
get_post_ancestorsは先祖ページのIDを配列として返す関数です。返される配列は親のIDに始まり、最後は親を持たない投稿。つまり、最上位の親投稿のIDになるので、array_popでこの配列の最後だけを抜き出します。
あとはget_permalinkで最上位の親のIDをリンクとして出力すれば親ページのリンクを子ページでも表示させる事が出来ますね。
仕上げ
<a href="<?php $ancestor = array_pop( get_post_ancestors( $post->ID ) ); $permalink = get_permalink( $ancestor ); echo ($permalink); ?> "> <?php $parent_title = get_the_title($post->post_parent); echo $parent_title; ?> </a>
親ページと子ページに親ページのタイトルとリンクを表示するコードが出来ました。
タイトルだけじゃ寂しいのでサブタイトルも表示させます。
親ページと子ページに親ページのサブタイトルを表示

サブタイトルも管理画面で・・となると最初に思いつくのはカスタムフィールドです。この際の注意点は、
- ループ外でカスタムフィールドを取得する必要がある
- 親投稿のカスタムフィールドだけで子ページにも共通で表示させる
というあたり。子ページ全てに親ページと同じカスタムフィールドを登録するのは凄く面倒だし、登録漏れも心配もあります。ここは、親ページのみの入力で済むようにしてあげたいですね。
まず、ループ外でカスタムフィールドを取得出来るようにします。
ループ外でカスタムフィールドを取得
カスタムフィールド名はfooと仮定します。
<?php
global $wp_query;
$postID = $wp_query->post->ID;
echo get_post_meta($postID, 'foo', true);
wp_reset_query();
?>
グローバル変数からIDを取得してget_post_metaで値を出力します。これでループ外でカスタムフィールドの値を表示させられました。
しかし、これではカスタムフィールドを登録してあるページにしか表示できません。
親ページのカスタムフィールドを子ページで取得
子ページで親ページのカスタムフィールドを取得するには$postID変数に親のIDを入れればOKですね。
<?php
global $wp_query;
//↓ ここが違うだけ
$postID = $wp_query->post->post_parent;
echo get_post_meta($postID, 'foo', true);
wp_reset_query();
?>
$wp_query->post->post_parent;とすれば、子ページで親ページのカスタムフィールドを取得できます。
最後に分岐させます。
仕上げ
<?php
global $wp_query;
if($post->post_parent)
$postID = $wp_query->post->post_parent;
else
$postID = $wp_query->post->ID;
echo get_post_meta($postID, 'foo', true);
wp_reset_query();
?>
親ページの時はそのページのカスタムフィールドを、それ以外のページはそのページの親のカスタムフィールドを取得して出力します。
これで「親投稿のカスタムフィールドだけで子ページにも共通でサブタイトルを表示させる」ことが出来ました。
最後に、親ページに属する子ページのリンクとタイトルをリストとして表示させます。
親ページと子ページに子ページのタイトルとリンクをリスト表示

これも、条件分岐を使います。wp_list_pagesでリスト表示させます。方法は上記と変わらないので一気に書きますね。
<?php
if($post->post_parent)
$children = wp_list_pages("sort_column=menu_order&title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("sort_column=menu_order&title_li=&child_of=".$post->ID."&echo=0");
if ($children) {
?>
親ページ、子ページで条件分岐してリストを作ればいいだけ。あとは任意の場所に出力します。
<ul> <?php echo $children; ?> </ul> <?php } ?>
これで、親ページ、子ページに共通の子ページリストが出来ました。
仕上げ
<?php
if($post->post_parent)
$children = wp_list_pages("sort_column=menu_order&title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("sort_column=menu_order&title_li=&child_of=".$post->ID."&echo=0");
if ($children) {
?>
<ul>
<?php echo $children; ?>
</ul>
<?php } ?>
wp_list_pagesのパラメーターはお好みで変えてください。
ゴール
出来たコードです。
<h3>
<a href="<?php //親ページのリンクを取得
$ancestor = array_pop( get_post_ancestors( $post->ID ) );
$permalink = get_permalink( $ancestor );
echo ($permalink);
?>">
<?php //親ページのタイトルを取得
$parent_title = get_the_title($post->post_parent);
echo $parent_title;
?>
<span><?php //サブタイトル部分。カスタムフィールドを親子両ページに出力する
global $wp_query;
if($post->post_parent)
$postID = $wp_query->post->post_parent;
else
$postID = $wp_query->post->ID;
echo get_post_meta($postID, 'foo', true);
wp_reset_query();
?>
</span></a></h3>
<?php //親に属する子ページのリンクとタイトルをリストで取得
if($post->post_parent)
$children = wp_list_pages("sort_column=menu_order&title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("sort_column=menu_order&title_li=&child_of=".$post->ID."&echo=0");
if ($children) {
?>
<ul>
<?php //リストを表示
echo $children;
?>
</ul>
<?php } ?>
これで、後で新しい親ページが増えても自動でメニューを実装出来ますね。
サブタイトルの表示をするのに、親ページでカスタムフィールドを入力してもらうのだけ忘れないようにして下さい。

↑ こんな感じで実装出来ました。※上記は親ページのリンクを子ページのリストに含めています。
ただ、僕はカスタムフィールドでしたが、他にも方法は有りますのでやりやすい方法でいいと思います。一例という事で。
子ページの表示順番を任意の順に変えるには
子ページのリンクリストの表示順を任意の順に変えたい場合は子ページの投稿画面で「ページ属性」っていうのがあるのでそこに順番を書けばその順通りに並びます。

これ。↑
あとは仕様に応じて工夫してください。サブタイトルじゃなくて共通のサムネイルっぽい画像を表示、とかでもいいんじゃないでしょうか。
以上です。

