【WordPress】サブメニューとして表示したカスタム投稿のカテゴリー表示

カスタム投稿をサブメニューとして登録した場合、タクソノミー(カテゴリー)を管理画面メニュー上に表示するのがややこしいのでまとめました。

    目指す状態

    目標としては図のような状態です。

    いろいろあって特定のカスタム投稿(カスタム投稿1)のサブメニューとして別のカスタム投稿(カスタム投稿2)を登録してあります。親になるトップレベルメニューはプラグインの設定画面なり、いろいろなパターンがあると思います。

    この記事では、カスタム投稿2のカテゴリーをサブメニューに表示させる方法を見ていきます。

    カスタム投稿をサブメニューとして登録

    まず、カスタム投稿1のサブメニューとしてカスタム投稿2をぶら下げる処理。

    register_post_typeshow_in_menuにカスタム投稿1の/wp-admin/以降の文字列を指定する。

    ‘tools.php’ や ‘edit.php?post_type=page’ のようなトップレベルのページを指定すると、この投稿タイプをそのサブメニューに配置する。

    関数リファレンス/register post type – WordPress Codex 日本語版
    PHP
    add_action( 'init', 'register_post_types' );
    function register_post_types(){
    	register_post_type( 'sample1',
    		array(
    			'label'  => 'カスタム投稿1',
    			'public' => true,
    		)
    	);
    
    	register_post_type( 'sample2',
    		array(
    			'label'        => 'カスタム投稿2',
    			'public'       => true,
    			'show_in_menu' => 'edit.php?post_type=sample1',
    		)
    	);
    }
    

    この状態になります。

    カスタム投稿にタクソノミーを追加

    トップレベルメニューのカスタム投稿の場合

    トップレベルメニューにあるカスタム投稿1であれば、以下のようにするだけでカテゴリーが追加される。

    PHP
    register_taxonomy( 'sample1-cat', 'sample1', array(
    	'label'        => 'カスタム投稿1のカテゴリー',
    	'public'       => true,
    	'hierarchical' => true,
    ));
    

    サブメニューのカスタム投稿の場合

    しかしカスタム投稿2では同様にしても、メニューにカテゴリーが表示されない。

    PHP
    register_taxonomy( 'sample2-cat', 'sample2', array(
    	'label'        => 'カスタム投稿2のカテゴリー',
    	'public'       => true,
    	'hierarchical' => true,
    ));
    

    ここで/wp-admin/edit-tags.php?taxonomy=sample2-catのURLを直接叩くと編集画面を表示することができる。

    つまりタクソノミー自体は追加されているが、メニューに表示されない状態になっている。

    show_in_menu は効かない

    register_taxonomy()Code Referenceを参照すると、パラメータにregister_post_typeと同様のshow_in_menuが見つかる。ので、ここに同じように文字列を入れたくなるが、true or false の2択となっていて同じように指定できない。

    PHP
    register_taxonomy( 'sample2-cat', 'sample2', array(
    	'label'        => 'カスタム投稿2のカテゴリー',
    	'public'       => true,
    	'hierarchical' => true,
    	'show_in_menu' => 'edit.php?post_type=sample1', // 効かない
    ));
    

    サブメニューのカスタム投稿のタクソノミーを表示させる

    add_submenu_pageをアクションフックadmin_menuにフックして使用する。

    第一引数の$parent_slugにはregister_post_typeshow_in_menuに設定したものと同様の文字列を指定する。 5番目の$menu_slugにはカテゴリーページ自身のスラッグ(edit-tags.php?taxonomy={タクソノミ名})を指定する。

    PHP
    add_action( 'admin_menu', 'show_taxonomy_under_specific_menu' );
    function show_taxonomy_under_specific_menu(){
    	add_submenu_page(
    		'edit.php?post_type=sample1', // $parent_slug
    		'カスタム投稿2のカテゴリー', // $page_title
    		'カスタム投稿2のカテゴリー', // $menu_title
    		'manage_options', // $capability
    		'edit-tags.php?taxonomy=sample2-cat&post_type=sample2' // $menu_slug
    	);
    }
    

    表示された。

    タクソノミー編集ページ表示時に正しい親メニューと紐付ける

    しかし追加された「カスタム投稿2のカテゴリー」のメニューをクリックすると…

    ページは正しく遷移するが、メニューバーが紐づいておらず、「投稿」のメニューが選択された状態になってしまうため修正する。

    「このサブメニューの親(トップレベルメニュー)はこれだよ」というのを指定する$parent_fileという変数があり、/wp-admin/menu-header.phpでフックが用意されているので、正しい親を紐付ける。

    PHP
    add_filter( 'parent_file', 'set_parent_file' );
    function set_parent_file( $parent_file ){
    	global $current_screen;
    	$taxonomy = $current_screen->taxonomy;
    	if ( $taxonomy == 'sample2-cat' ) {
    		$parent_file = 'edit.php?post_type=sample1';
    	}
    	return $parent_file;
    }
    

    正しく紐づいた状態。

    タクソノミー編集ページ表示時にサブメニューを太字にする

    カテゴリー編集ページに居る際に、メニューが太字(current)にならない。

    上記状態では、「カスタム投稿2のカテゴリー」編集ページ表示を開いているにもかかわらず、メニューが太字でハイライトされない。

    これは/wp-admin/menu-header.phpの以下の箇所の比較で失敗しているため。

    menu-header.php
    if ( isset( $submenu_file ) ) {
    	if ( $submenu_file == $sub_item[2] )
    		$class[] = 'current';
    ...
    }
    

    上記でそれぞれの変数には以下が入っており、イコールにならない。

    • $submenu_file → string(56) “edit-tags.php?taxonomy=sample2-cat&post_type=sample2”
    • $sub_item[2] → string(52) “edit-tags.php?taxonomy=sample2-cat&post_type=sample2”

    そこでフィルターフックsubmenu_fileで$submenu_fileにエスケープされていない値を入れ直す。

    PHP
    add_filter( 'submenu_file', 'highlight_taxonomy_menu' );  
    function highlight_taxonomy_menu( $submenu_file ){
    	if( esc_html( 'edit-tags.php?taxonomy=sample2-cat&post_type=sample2' ) == $submenu_file ){
    		$submenu_file = 'edit-tags.php?taxonomy=sample2-cat&post_type=sample2';
    	}
    	return $submenu_file;
    }
    

    完成。

    post_typeのパラメータを付けない場合

    以下のように&post_type=sample2のパラメータを付けなかった場合でも、メニューは正しく表示される。

    PHP
    add_action( 'admin_menu', 'show_taxonomy_under_specific_menu' );
    function show_taxonomy_under_specific_menu(){
    	add_submenu_page(
    		'edit.php?post_type=sample1', // $parent_slug
    		'カスタム投稿2のカテゴリー', // $page_title
    		'カスタム投稿2のカテゴリー', // $menu_title
    		'manage_options', // $capability
    		//'edit-tags.php?taxonomy=sample2-cat&post_type=sample2' // $menu_slug
    		'edit-tags.php?taxonomy=sample2-cat' // $menu_slug
    	);
    }
    

    ただしこの場合、「カウント」のリンクが正しく紐づかず、通常の「投稿」(post_type=post)でタクソノミーを探しに行ってしまうので、post_typeのラメータは省略しない方が良い。

    一番いいのは…

    そもそも普通にメインメニューとして扱っていいなら、こんなややこしいことする必要ないので、まずはこうして差し支えないか確認するのがよいと思いました。

    シェア
    野良人 代表
    新免祥太
    1988年岡山生まれ。外食企業のWEB・EC担当を経験したのち、2013年12月より「野良人(のらんど)」の屋号で独立しWEBデザイン・プログラミングなどWEBサイト制作の工程全般を請け負っています。お気軽にご相談ください。
    広告
    <次の記事(2021/05/26)
    ソーシャルボタンをオリジナルデザインで実装
    前の記事>(2021/01/19)
    PHPのOpenSSLで暗号化して復号する
    記事一覧