はぴすぷ

【WordPressプラグイン開発】管理画面にメニュー・サブメニューを追加する方法

      2015/11/30

前回プラグインの雛形を作るところまでは出来たので、管理画面にメニューを追加する方法を紹介します。

前回:【WordPressプラグイン】え?超簡単じゃん!プラグイン開発は実は難しくなかった!

追加すること自体は簡単なんですが、思った通りに実装するのはちょっと難しかったので、ちょっと手間取りました(;´∀`)

最近、統合開発環境の「PhpStorm」を導入したので、「Codex」を確認するだけで満足せず、WordPressの中身を見るようになりましたw

本格的にプラグイン作るなら、WordPressのこともっと詳しくならないとね( ・`ω・´)

というわけで、説明していきます!

スポンサーリンク

管理画面のメニューの構造を理解する

まず管理画面のメニューがどういう構造になっているかを知りましょう。

通常のシングルサイトの場合

こちらが、最初の状態の管理者に表示されるメニュー。

SS_4694

何のプラグインも入れていない、まっさらな状態です。懐かしいですね。

気づいた人も多いと思いますが、「ダッシュボード」や、「コメント」の下に少し隙間があります。

この隙間で分類分けがされていて、「ダッシュボード」は特になし、「投稿、メディア、固定ページ」などは「オブジェクト」、「外観、プラグイン、ツール、設定」などは「ユーティリティ」という扱いになっています。

実はこの「各メニュー」と「隙間」は、「$menu」というグローバル変数の配列で、以下の添え字にそれぞれ入っています。

添え字 タイトル 権限 スラッグ
2 ダッシュボード read index.php
4 (セパレーター) read separator1
5 投稿 edit_posts edit.php
10 メディア upload_files upload.php
15 リンク manage_links link-manager.php
20 固定ページ edit_pages edit.php?post_type=page
25 コメント edit_posts edit-comments.php
59 (セパレーター) read separator2
60 外観 switch_themes themes.php
65 プラグイン activate_plugins plugins.php
70 ユーザー list_users users.php
75 ツール edit_posts tools.php
80 設定 manage_options options-general.php
99 (セパレーター) read separator-last

添え字の小さい順に並べて表示されるので、WordPressが標準で使用している添え字以外に、新しく作るメニューを登録してあげれば、その数値に応じた場所に表示されることになります。

ちなみに「権限」の欄は、この権限グループを与えられているユーザーだけに表示されるという意味。

権限の種類は大量にあるので、こちらを確認して見てください。
ユーザーの種類と権限 – WordPress Codex 日本語版

「スラッグ」の欄は、メニューをクリックした時に表示する、ページのファイルとパラメータ。単にユニークな識別子である場合もある。

赤で塗っている15の「リンク」は、ソース上はまだ存在しますが、恐らく今後削除されるだろう機能なので、無理やり表示させない限りは表示されません。

マルチサイトの場合

実はマルチサイトとか言う機能があるのを知りませんでした。1つのWordPressで複数のブログを持てるように出来る機能のようです。

試してみると、アメブロとかみたいに、ブログスペースを提供出来るようになったりも出来ました。長くなるのでマルチサイトの説明はこれまで!

そして、マルチサイトの場合の管理者のメニューはこんな感じです。

SS_4695

ソースを見ましたが、こちらはセパレーターがあっても分類分けはされていませんでした。「$menu」に格納される内容はこちら。

添え字 タイトル 権限 スラッグ
2 ダッシュボード manage_network index.php
4 (セパレーター) read separator1
5 サイト manage_sites sites.php
10 ユーザー manage_network_users users.php
15 テーマ manage_network_themes themes.php
20 プラグイン manage_network_plugins plugins.php
25 設定 manage_network_options options-general.php
30 更新
99 (セパレーター) exist separator-last

赤で塗っている30の「更新」は、メニュー周りのCodexを見ると、ネットワーク管理者(マルチサイトの管理者)に表示されるように書いていますが、ソース上からは完全に消えてました。

関数リファレンス/add menu page – WordPress Codex 日本語版

日本語版の情報が古くなっているのかと思って、本家のCodexを確認しましたが、同じようにメンテされていませんでした。
Function Reference/add menu page « WordPress Codex

マルチサイト自体使っている人がいるのか不明ですが、殆どのプラグインが通常のシングルサイトに向けて作っているので、マルチサイトでは殆ど正常に動きませんでした。

テーブルの作成やオプションの保存が、親のサイトのテーブルプレフィックスに向いてるからっぽい。この辺ちゃんとマルチサイト対応しておけば…。いや、需要あるんだろうか(;´Д`)

そんな手間なことじゃないと思うので、対応しておけば「マルチサイト対応」とか謳えます!誰得なのか分かりませんけどw

管理画面にメニューを追加する方法

メニューの構造が分かったので、メニューを追加します。

メニューを追加する関数はこちら。

add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null );
  1. $page_title:クリックして表示されるページのタイトル
  2. $menu_title:メニューに表示されるタイトル
  3. $capability:表示に必要なユーザーの権限
  4. $menu_slug:クリックした時に実行するファイルとパラメータ。もしくは一意な識別子。
  5. $function:クリックした時に実行する関数名。
  6. $icon_url:メニューの横に表示されるアイコン画像のURL。もしくは標準で用意されているアイコンのクラス名。
  7. $position:表示位置。(他とかぶるとどちらかが消滅する)(小数を指定可能。但し文字列にすること。)

ちょっと分かり辛いので、使い方のサンプルをいくつかあげます。

サンプル1

$menu_slugで実行ファイルを指定する方法。権限は購読者以上を想定。

add_menu_page('スラッグ', 'スラッグ', 'read', '../wp-content/plugins/my-test/slug.php');

この方法は、色んなプラグインを見ましたが誰も使ってませんでした!

完全に別ページに飛ばしちゃうので、WordPressの管理画面のコンテンツ部分だけを作成したい場合だと、一筋縄ではいかなくなります。

完全に別ページを実装したいんだ!という場合以外は、$functionを指定しましょう!

ちなみにこんな感じに表示されます。

SS_4696

アイコンを指定していないので、デフォルトの歯車アイコンで、位置も指定していないので、一番最後のセパレーターの99以降の100から順に追加されます。

クリックした時に表示されるのは、用意したphpファイルの内容そのものです!

サンプル2

$functionを用意して、アイコンはオリジナルの画像を指定、位置はメディアのすぐ後にする。権限は編集者以上を想定。

add_menu_page('メディア下', 'メディア下', 'moderate_comments',
    'my_test_menu',
    'mt_under_media',
    plugins_url('/images/logo.png', __FILE__),
    '10.00326');

function mt_under_media() {
    echo "<h2>メディア下のメニューをクリックした時に表示される内容</h2>";
}

これでオリジナルアイコンが付いたメニューが表示されます。そしてメニューをクリックした時に「mt_under_media()」を実行した結果が、管理画面のコンテンツ部分に表示されます。

SS_4697

この時、URLは「http://example.com/wp-admin/admin.php?page=my_test_menu」のように、$menu_slugで指定したものがpageの値になります。

ちなみに$positionに’10.00326’とよく分からない値にしているのは、衝突を回避する目的です。

サンプル3

オブジェクトグループ(投稿や固定ページなど)の下に追加して、アイコンを指定する。権限は管理者以上を想定。

add_object_page('オブジェクト', 'オブジェクト', 'manage_options',
    'my_test_object',
    'my_test_object',
    'dashicons-carrot');

function my_test_object() {
    echo "<h2>オブジェクトのメニューをクリックした時に表示される内容</h2>";
}

今回は「add_menu_page()」関数ではなく、「add_object_page()」を使用しています。

単純に「add_menu_page()」の最後の引数の$positionである位置を、安全にオブジェクトグループの末尾に設定してくれるようにラップした関数です。ユーティリティグループについて同じように動作する「add_utility_page()」もあります。

アイコンはWordPressのDashiconsのクラスを指定してニンジンアイコンにしてみました。

SS_4699

Dashiconsはこちらで使いたいものを探してクラス名を確認しましょう。
WordPress › Dashicons | WordPress Developer Resources

メニュー作成のフックに登録する

メニューを追加する「add_menu_page()」の使い方を説明しましたが、実はそのまま書くだけでは以下のようにエラーになります。

Fatal error: Call to undefined function add_menu_page()

プラグインの読み込み時にはまだ定義されていないので、実際にメニューを作成するタイミング「admin_menu」で呼ばれるように、フックに登録しておきます。

add_action('admin_menu', 'mt_add_pages');

function mt_add_pages() {
    add_menu_page('~略~');
}

これで管理画面に新しいメニュー項目と、クリックした時に表示する画面を表示することが出来ます。

管理画面にサブメニューを追加する方法

先程まではメインになるメニューを新規に追加する方法でした。

次はメニューの下にぶら下がっている、サブメニューについてです。

サブメニューの構造について

メニューと同じような感じです。長くなるので「ダッシュボード」と「投稿」だけ載せておきます。

親スラッグ 添え字 タイトル 権限 スラッグ
index.php
(ダッシュボード)
0 ホーム read index.php
10 更新 update_core update-core.php
edit.php
(投稿)
5 投稿一覧 edit_posts edit.php
10 新規追加 edit_posts post-new.php
15 カテゴリー manage_categories edit-tags.php?taxonomy=category
16 タグ manage_categories edit-tags.php?taxonomy=post_tag

サブメニューの情報は、グローバル変数「$submenu」で管理されていて、親のスラッグに対して配列で各項目の情報を持っています。

サブメニューを追加する関数

構造が分かった所で、ここに情報を追加する関数を紹介します。

add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' );
  1. $parent_slug:親のスラッグ
  2. $page_title:クリックして表示されるページのタイトル
  3. $menu_title:メニューに表示されるタイトル
  4. $capability:表示に必要なユーザーの権限
  5. $menu_slug:クリックした時に実行するファイルとパラメータ。もしくは一意な識別子。
  6. $function:クリックした時に実行する関数名。

説明要らないよね(^q^)メインのメニューとほぼ同じです!

増えたのは、何の下にぶら下げるかを指定する「$parent_slug」のみです。

逆にアイコンと位置の引数が減りました。アイコンは良いとして位置を決められないのは…。なので、複数追加したい時は上に表示したい順に呼びましょう。

一応この関数でやってることを真似れば任意の位置に差し込むことは出来ますが、WordPressのアップデートで仕様が変わってしまった時に、不具合を起こすことになりかねません。なるべく用意されている関数を通した方が良いです。

メインのメニューには後からフィルターで順序を並び変えられるのですが、サブメニューは用意されていないので諦めましょう…。
Plugin API/Filter Reference/custom menu order « WordPress Codex

標準メニューに追加するラップ関数

自分で用意したメニューのスラッグなら当然のように分かるんですが、WordPress標準のメニューのスラッグなんて覚えてませんよね。

なので、分かりやすいラップ関数が用意されています。意味不明な文字列を指定するよりは、後から見て分かりやすいこちらを使ったほうが良いかと思います。

第1引数の「親スラッグ」だけ追加して、「add_submenu_page」を呼んでくれます。

add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function);

以下の関数で標準のものは全てサポートされています。

  • add_dashboard_page:ダッシュボード
  • add_media_page:メディア
  • add_pages_page:固定ページ
  • add_comments_page:コメント
  • add_theme_page:外観
  • add_plugins_page:プラグイン
  • add_users_page:ユーザー
  • add_management_page:ツール
  • add_options_page:設定

まとめ

  • メニューにはトップレベルの「メニュー」と、その下にぶら下がる「サブメニュー」がある。
  • メニューを作成するには管理メニュー(admin_menu)にフックが必要。
  • メニューをクリックした時に表示する画面の作成はfunctionで返す方法がおすすめ。

最終サンプル

// 管理メニューにフックを登録
add_action('admin_menu', 'mt_add_pages');

// メニューを追加する
function mt_add_pages()
{
    // プラグインのスラグ名はユニークならなんでも良い
    // /plugin/my-test/my-test.phpに置いているので
    $my_plugin_slug = plugin_basename(__FILE__);

    // トップレベルにオリジナルのメニューを追加(購読者相当)
    add_menu_page('まとめ', 'まとめ', 'read',
        $my_plugin_slug,
        'mt_menu_index',
        plugins_url('/images/logo.png', __FILE__)
    );
    
    // オリジナルのメニューの最初の項目のメニュータイトルを置き換えてます。
    // 他に良い方法あるかもしれません(;´∀`)別にこれはしなくていいよ!
    add_submenu_page($my_plugin_slug, 'まとめ', 'はじめに',
        'read',
        $my_plugin_slug,
        'mt_menu_index');

    // オリジナルのメニューにサブメニューを追加(編集者相当)
    add_submenu_page($my_plugin_slug, 'サブメニュー1', 'サブメニュー1',
        'moderate_comments',
        'submenu-1',
        'mt_submenu_page1');

    // オリジナルのメニューにサブメニューを追加(管理者相当)
    add_submenu_page($my_plugin_slug, 'サブメニュー2', 'サブメニュー2',
        'manage_options',
        'submenu-2',
        'mt_submenu_page2');


    // 既存の「設定」メニューにサブメニューを追加:
    add_options_page('マイオプション', 'マイオプション',
        'manage_options',
        'mt-options-submenu',
        'mt_options_page');
}

// メニューがクリックされた時にコンテンツ部に表示する内容
function mt_menu_index() {
?>
    <h2>「まとめ」をクリックした時に表示される内容</h2>
    <p>サブメニューの最初の項目を「まとめ」から「はじめに」に置き換えてます!</p>
    <p>こんな感じで普通のhtmlを書いても大丈夫ですし、別のファイルを「require」なり「include」しても良いと思います。</p>
<?php
}
function mt_submenu_page1() {
    echo "<h2>「サブメニュー1」をクリックした時に表示される内容</h2>";
}
function mt_submenu_page2() {
    echo "<h2>「サブメニュー2」をクリックした時に表示される内容</h2>";
}
function mt_options_page() {
    echo "<h2>「設定」内の「マイオプション」をクリックした時に表示される内容</h2>";
}

これで、こんな感じになります。

SS_4702

メニューの1番下にオリジナルのメニュー「まとめ」とそのサブメニューが追加されて、既存の「設定」にも「マイオプション」が追加されました。

終わりに

管理画面に自分でメニュー追加出来るようになると色々と捗りますね( ・`ω・´)

気になったことは直接データベースを覗いて確認していたんですが、これでいい感じに管理画面で表示出来るようになりそうです。

それと、ユーザーの権限についても勉強出来たので、広告管理機能を作って広告主に効果確認とかして貰えるページも作れそう。

別にWordPress通す必要もないんですけどねw

一から全部開発するよりWordPressの機能を使ったほうが効率的ですしね!

結構ボリュームがでかくなったので、設定を登録したり変更したりする機能については次回説明したいと思います!

是非みなさんもプラグイン作ってみて下さい!

それでは!

2015/11/30追記:書きました!
【WordPressプラグイン開発】独自設定ページでオプションを追加・変更する方法

 - WordPress, プラグイン