【WordPress】管理画面に独自メニューページを追加する

functions.php で add_menu_page() という関数を用いると、管理画面に独自メニューページを追加することができます。以下、その方法についてまとめます。
独自メニューページの追加
admin_menu フックで add_menu_page() という関数を以下のように呼び出せば、独自のメニューページを追加できます。
add_action('admin_menu', 'add_original_menu');
function add_original_menu() {
add_menu_page('オリジナルメニューテスト', 'テスト', 'edit_posts', 'original-menu-test', 'original_menu_setting', 'dashicons-admin-generic', 80);
}
function original_menu_setting(){
// 一旦空の関数を定義する
}

少々引数が多いのですが、以下のようになっています。
add_menu_page(第一引数, 第二引数, 第三引数, 第四引数, 第五引数, 第六引数, 第七引数);
- 第一引数:メニューが選択されたときのタイトルタグの出力内容
- 第二引数:メニューバーの表示名(上記の例だと「テスト」)
- 第三引数:メニューを表示する権限(上記の例だと「投稿者」相当)
- 第四引数:メニューが選択されたときの URL スラッグ
- 第五引数:ページのコンテンツを表示するための関数
- 第六引数:メニューバーの表示アイコン(参考)
- 第七引数:メニューバーでのメニューの表示位置(値が大きいほど下に表示)
独自メニューページの設定
先ほど空だった関数、original_menu_setting() の中身を以下のように修正し、HTMLを出力するようにします。データ入力用のテキストボックスと、送信ボタンを配置しています。
<?php
function original_menu_setting(){
$user_id = get_current_user_id();
?>
<div class="wrap">
<h1 class="wp-heading-inline">テストページ</h1>
<form method="post" action="">
<?php wp_nonce_field('wp-nonce-confirm', 'wp_nonce_confirm_option'); ?>
<h2>テスト入力欄</h2>
<table class="form-table" role="presentation">
<tbody>
<tr>
<th scope="row">入力欄</th>
<td>
<input type="text" name="test_text" id="test_text" class="regular-text" value="<?php echo esc_attr(get_user_meta($user_id, 'test_value', true)); ?>">
</td>
</tr>
</tbody>
</table>
<?php submit_button('変更を保存', 'primary', 'submit_test'); ?>
</form>
</div>
<?php
}
?>
wp_nonce_field() は送信時にセキュリティを高めるため、テンポラリパスワードを発行するような関数です。submit_button() は送信ボタンを追加する WordPress 関数で、第一引数がボタンの表示ラベル、第二引数が使用 CSS、第三引数が name、id 属性となっています。フォーム送信後は現在のページに留まるよう、action=”” としています。
以下のように独自メニューページが表示されます。

値の受け渡し
POST 送信されたデータを取得するには、admin_init フックを使います。管理画面にアクセスする際に発火するフックなので、もっと良さそうなフックがあるかもしれません。
$_POST 変数が空でない場合かつ nonce が適切な場合に限り、テキストボックスの値をユーザーメタデータに保存します。
add_action('admin_init', 'save_test_settings');
function save_test_settings(){
if(!empty($_POST)){
$user_id = get_current_user_id();
if (!isset($_POST['wp_nonce_confirm_option'] ) || !$_POST['wp_nonce_confirm_option']){
return;
}
if (!check_admin_referer('wp-nonce-confirm', 'wp_nonce_confirm_option')){
return;
}
if(isset($_POST['submit_test'])){
if(isset($_POST['test_text'])){
update_user_meta($user_id , 'test_value', sanitize_text_field($_POST['test_text']));
add_action('admin_notices', 'data_update_notices');
}
}
}
}
function data_update_notices(){
global $pagenow;
if ($pagenow=='admin.php') {
echo '<div class="updated"><p>設定を保存しました。</p></div>';
}
}
実行した結果は以下の通りです。テキストボックスの値が保存され、notice が表示されます。

全体のソースコードは以下のようになります。
<?php
add_action('admin_menu', 'add_original_menu');
function add_original_menu() {
add_menu_page('オリジナルメニューテスト', 'テスト', 'edit_posts', 'original-menu-test', 'original_menu_setting', 'dashicons-admin-generic', 80);
}
function original_menu_setting(){
$user_id = get_current_user_id();
?>
<div class="wrap">
<h1 class="wp-heading-inline">テストページ</h1>
<form method="post" action="">
<?php wp_nonce_field('wp-nonce-confirm', 'wp_nonce_confirm_option'); ?>
<h2>テスト入力欄</h2>
<table class="form-table" role="presentation">
<tbody>
<tr>
<th scope="row">入力欄</th>
<td>
<input type="text" name="test_text" id="test_text" class="regular-text" value="<?php echo esc_attr(get_user_meta($user_id, 'test_value', true)); ?>">
</td>
</tr>
</tbody>
</table>
<?php submit_button('変更を保存', 'primary', 'submit_test'); ?>
</form>
</div>
<?php
}
add_action('admin_init', 'save_test_settings');
function save_test_settings(){
if(!empty($_POST)){
$user_id = get_current_user_id();
if (!isset($_POST['wp_nonce_confirm_option'] ) || !$_POST['wp_nonce_confirm_option']){
return;
}
if (!check_admin_referer('wp-nonce-confirm', 'wp_nonce_confirm_option')){
return;
}
if(isset($_POST['submit_test'])){
if(isset($_POST['test_text'])){
update_user_meta($user_id , 'test_value', sanitize_text_field($_POST['test_text']));
add_action('admin_notices', 'data_update_notices');
}
}
}
}
function data_update_notices(){
global $pagenow;
if ($pagenow=='admin.php') {
echo '<div class="updated"><p>設定を保存しました。</p></div>';
}
}
?>
少し宣伝
当サイトは WordPress 自作テーマを用いた海外旅ブログまとめサイトとなっています。トップページに地図がありますが、地名を押すと画像が開き、画像を押すと関連記事一覧(クリック数順)が開きます。記事数が多い国ほど赤く、地名もその国で記事が多い都市の文字が大きくなるようにしています。ぜひ覗いてみてください。
当サイトで海外旅ブログを執筆することも可能です(もちろん無料です)! また既にブログをお持ちの方も、当サイトからリンクを貼ることができるようになっています。パントレ開発部までお気軽にお問い合わせください。
このページが皆様のプログラミングの一助となりますことをお祈りいたします
パントレ開発部