WordPress 子ページ メニュー ウィジェット

WordPress で指定した固定ページの子ページをメニュー表示するウィジェットを作成してみました。

仕様

  • 表示する固定ページ(親ページ)を指定する。
  • 階層数を指定する。
  • 子ページがない場合、ウィジェット自体を表示しない。

PHP コード

functions.php などに下記のコードを記述します。

/**
 * 子ページメニューウィジェット
 *
 * @version 1.1.0
 * @see WP_Widget
 */
class WP_Widget_Children_Pages extends WP_Widget {

	function __construct() {
		parent::__construct( 'children-pages', $name = '子ページ', array( 'classname' => 'widget_children_pages', 'description' => '子ページ一覧' ) );
	}

	function widget( $args, $instance ) {
		extract( $args );
		$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
		$page_id = empty( $instance['page_id'] ) ? 0 : $instance['page_id'];
		$depth = $instance['depth'];

		if ( $page_id && $children = wp_list_pages( array( 'title_li' => '', 'depth' => $depth, 'child_of' => $page_id, 'echo' => false, 'sort_column' => 'menu_order' ) ) ) {
			echo $before_widget;
			if ( $title ) echo $before_title . $title . $after_title;
			echo '<ul>' . $children . '</ul>';
			echo $after_widget;
		}
	}

	function update( $new_instance, $old_instance ) {
		return $new_instance;
	}

	function form( $instance ) {
		$instance = wp_parse_args( (array) $instance, array( 'page_id' => '', 'title' => '' ) );
		$title = esc_attr( $instance['title'] );
		$page_id = esc_attr( $instance['page_id'] );
		$depth = isset( $instance['depth'] ) ? intval( $instance['depth'] ) : 0;
		?>
		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
			<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo $title; ?>" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'page_id' ); ?>"><?php _e( 'Pages:' ); ?></label><br />
			<select id="<?php echo $this->get_field_id( 'page_id' ); ?>" class="widefat" name="<?php echo $this->get_field_name( 'page_id' ); ?>">
				<option value=""></option>
				<?php
				$posts = get_posts( array( 'post_type' => 'page', 'numberposts' => -1 ) );
				foreach( $posts as $post ) {
					echo '<option value="' . $post->ID . '"' . selected( $instance['page_id'], $post->ID ) . '>' . $post->post_title . "</option>\n";
				}
				?>
			</select>
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'depth' ); ?>">階層数:</label><br />
			<select id="<?php echo $this->get_field_id( 'page_id' ); ?>" class="widefat" name="<?php echo $this->get_field_name( 'depth' ); ?>">
				<option value="0"<?php selected( $depth, 0 ); ?>>インデントあり</option>
				<option value="-1"<?php selected( $depth, -1 ); ?>>インデントなし</option>
				<?php
				for ( $i = 1; $i <= 10; $i++ ) {
					echo '<option value="' . $i . '"' . selected( $depth, $i, false ) . '>' . $i . "</option>\n";
				}
				?>
			</select>
		</p>
		<?php
	}
}

add_action( 'widgets_init', function() { register_widget( 'WP_Widget_Children_Pages' ); } );

スタイル (CSS)

出力する HTML はカスタム メニュー ウィジェットと同じ構成です。とくにスタイルを追加しなくてもテーマのスタイルが反映されると思います。反映されない場合は、カスタム メニュー ウィジェットのスタイルを参考に追加してください。

更新履歴

2020年9月4日

  • 階層数のセレクトボックスで正しい階層数が選択されていない不具合を修正しました。(Special thanks to プログレス合同会社 山口)

コメント

  • いつも参考にさせていただいています。
    固定ページサイドバーでの子ページメニュー表示をVK All in One Expansion Unitから切り替えるべくコードを眺めていたのですが、50行目と51行目はが抜けているのではないでしょうか?

    • こんにちは、コメントありがとうございます。
      思いっきり間違えていました。2年間も間違ったままでお恥ずかしい限りです (^^;
      また何かありましたらコメントください。ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。

日本語でコメントを入力してください。(スパム対策)