wp_list_pagesで関連する固定ページのみを表示
2017.09.18
 
  大量のページのあるサイト
大きな企業や公共期間等のホームページは、サイトのページ数が数百とかざらにあったりします。
ページの階層は4、5段は当たり前、自由にどこまでもいけるので、ちゃんと決めておかないと、階層がどんどん深くなってしまいます。
以前にもこちらで書いたのですが、固定ページで階層構造を作るには、管理画面の固定ページと、カスタムメニューがあります。
カスタムメニューはマウスで簡単に階層構造が作れる機能ではありますが、ホームページの構造に関わる固定ページでの階層管理は、固定ページの階層でしっかり作成する必要があります。
それに大量のページの階層をマウスで再度構築るというのは、かなり面倒な作業です。
  固定ページの階層構造を表示してくれるwp_list_pagesはwordpress初期からある実に頼りになる関数です。この関数を使って階層を表示する事にします。
固定ページの整理された表示方法
今回やりたい事は、こちらの記事の中の「現在開いているページに関係のない子ページを閉じておく」と同じ事を wp_list_pageでも実現します。

さて、今回お題の件ですが、サイト製作の時に需要があったので、探してみたのですが、見つかりませんでした。昔はプラグインがあった気がしたのですが、どこにいったのか。。
  公式ページのwp_list_pagesのマニュアルにそれっぽい事が書いてあるのですが、、
いくつか実装例をみると、若干違ったり、ID直接指定していたりと、あまり実用には向かないようです。
基本的な考え方(アルゴリズム)としては、wp_list_pagesで表示しようとするページ要素に対し、
「現在のページを含む先祖達のページIDを親に持つページ」以外を非表示にする
というフィルターを設置します。
  便利な関数get_post_ancestorsです。この現在のページの親階層をたどってその祖先達のIDを配列で返してくれます。パンくずの表示につかえますね。
wp_list_pageの表示ページ要素に対しフィルターをかけるなら、こちらに紹介されている get_pagesにフィルターを追加するか、次に紹介するWalker_Pageを継承したwalkメソッドを定義します。
class My_Walker_Page extends Walker_Page {
	// filter $elements
	public function walk( $elements, $max_depth ) {
        	$func_args = func_get_args();
		$r = $func_args[2];
		$current_page = $func_args[3];
		$filtered_elements = my_walker_element_filter( $elements,  $current_page );
		return parent::walk( $filtered_elements, $max_depth,  $r, $current_page );
	}
}
次にelementに対しフィルターをかけます。
function my_walker_element_filter( $elements, $current_page ) {
	$ancestors = get_post_ancestors( $current_page );
	$ancestors[] = $current_page;
	$ancestors[] = 0; /* 第一階層も含める場合 */
	$out_elements = [];
	foreach( $elements as $e ) {
		if ( in_array( $e->post_parent, $ancestors, true ) ) {
			$out_elements[] = $e;
		}
	}
	return $out_elements;
}
これで定義ができました。では wp_list_page を呼び出して実際に利用してみます。
表示したい部分のテンプレートの箇所に下のコードを入れます。
- 
<?php wp_list_pages( [ 'title_li' => '', 'walker' => new My_Walker_Page() ] ); ?>

うまくいったかと思います。
wp_list_pagesのカスタマイズをウィジェットで利用
もし、wp_list_pagesではなく、ウィジェットの「固定ページ」で資料したい場合は下記
のようにwp_list_pagesに対する引数walkerの設定を変更するようにfunctions.phpに追加します。
function my_widget_pages_args( $args ) {
	$args['walker'] = new My_Walker_Page();
	return $args;
}
add_filter( 'widget_pages_args', 'my_widget_pages_args', 10, 1 );
これで「外観」>「ウィジェット」から固定ページをセットするだけで、関連ページのみの表示をする
環境が得られます。
以上、固定ページのメニューを表示する時に、余計な情報を隠しておくというのはありがちなtipsかと思ったのですが、いろいろネットを探し回っても見つからなかったので書いてみました。
お役に立てれば幸いです。