WordPressで管理画面を作成する方法

管理画面

管理ページを追加する方法について。

メニューの追加

まず管理画面を追加する簡単な例です。

// admin_menuアクションでメニュー追加を定義
add_action('admin_menu', function(){

    // メニューの情報。
    add_menu_page(
        'クラゲ管理画面',
        'クラゲメニュー設定',
        'manage_options',
        'kurage',
        function()
        {
            echo '<h2>クラゲの設定項目・・・</h2>';
        }
    );

});

管理画面にメニュー(クラゲメニュー設定)が表示されるのでそれをクリック。

admin_menuフックの中でadd_menu_page()を使用します。
第一引数は管理ページのタイトル(タイトルバーに表示される)、
第二引数はメニューのタイトル(画面左のメニューに表示される)、
第三引数は権限(ここでは説明しません)、
第四引数にスラグ(今回はkurageとしました。)
第五引数は管理画面に表示する内容をコールバックで指定できます。

後の引数は省略。

スラグにkurageを指定した場合、メニューを開いた時のURLには

admin.php?page=kurage

のようなクエリが追加されてます。

隠しフィールド

入力値を送信するためにまずsettings_fields()submit_button()を追加します。
管理画面に表示するコールバック関数を定義しました。

add_action('admin_menu', function(){

    $showPage = function()
    {
        ?>

        <div class="wrap">

            <h2>テキストの追加</h2>

            <form action="options.php" method="POST">
                <?php settings_fields('kurage') ?>
                <p>ここにいろんな入力フィールドを置く・・・</p>
                <?php submit_button() ?>
            </form>

        </div>

        <?php
    };

    add_menu_page(
        'クラゲ管理画面',
        'クラゲメニュー設定',
        'manage_options',
        'kurage',
        fn() => $showPage()
    );

});

まずはフォームです。

<form action="options.php" method="POST">

宛先はoptions.phpで、メソッドをPOSTにして送信するようにします。
ただそれだけでは役不足です。
隠しフィールドに必要な情報を持たせないといけません。
それをやってくれるのがsettings_fields()です。

settings_fields('kurage')

引数にスラグを指定します。
この関数は以下の隠し要素を吐き出します。

<input type="hidden" name="option_page" value="kurage">
<input type="hidden" name="action" value="update">
<input type="hidden" id="_wpnonce" name="_wpnonce" value="16a1d9fd5f">
<input type="hidden" name="_wp_http_referer" value="/wp-admin/admin.php?page=kurage">

option_pageでスラグ(今回はkurage)を保持します。
actionupdateになるとoptions.phpは更新作業だと判断します。
_wpnonceはセキュリティ対策のものでCSRF攻撃を回避するためのナンスを忍ばせます。

次に送信ボタンです。

submit_button()

以下のHTMLを吐き出します。

<p class="submit">
    <input type="submit" name="submit" id="submit" class="button button-primary" value="変更を保存">
</p>

早速送信ボタンを押す!

・・・。

オプションとの連携

WordPressのオプションについてあらかじめ知っておく必要があります。
データベースにwp_optionsというテーブルがあって、
WordPressでKeyValue的なデータを扱うものです。
分からない人はget_option()set_option()などを調べてみてください。

WordPressのoptions.phpはこのオプションをうまく処理してくれます。

add_action('admin_menu', function(){

    function showPage()
    {
        ?>

        <div class="wrap">

            <h2>テキストの追加</h2>

            <form action="options.php" method="POST">

                <?php settings_fields('kurage') ?>

                <h3>text 1</h3>
                <input
                    type="text"
                    id="kurage_text_1"
                    name="kurage_text_1"
                    value="<?php echo esc_attr( get_option('kurage_text_1') ) ?>" />

                <h3>text 2</h3>
                <input
                    type="text"
                    id="kurage_text_2"
                    name="kurage_text_2"
                    value="<?php echo esc_attr( get_option('kurage_text_2') ) ?>" />

                <h3>text 3</h3>
                <input
                    type="text"
                    id="kurage_text_3"
                    name="kurage_text_3"
                    value="<?php echo esc_attr( get_option('kurage_text_3') ) ?>" />

                <?php submit_button() ?>
            </form>

        </div>

        <?php
    }

    add_menu_page(
        'クラゲ管理画面',
        'クラゲメニュー設定',
        'manage_options',
        'kurage',
        function()
        {
            showPage();
        }
    );

});

add_action('admin_init', function(){

    register_setting('kurage', 'kurage_text_1');
    register_setting('kurage', 'kurage_text_3');

});

以下のページが表示されるので、適当に入力していきます。

送信ボタンを押した後、DBを確認してみましょう。
以下のクエリを投げます。

select * from wp_options where option_name like 'kurage\_text\_%';

kurage_text_1には111が、
kurage_text_3には333が入ってます。

ただし、

kurage_text_2には222は入ってません。

どのような仕組みでしょう!?
まずフォームの一つ目を見てください。

<input
    type="text"
    id="kurage_text_1"
    name="kurage_text_1"
    value="<?php echo esc_attr( get_option('kurage_text_1') ) ?>" />

namekurage_text_1となってます。
valueはオプションからkurage_text_1を取得してサニタイズしたものを与えてます。
他の入力要素も同じような感じです。

ボタンを送信するとkurage_text_1, kurage_text_2, kurage_text_3の入力値が送信されます。

次にPHP側の設定です。

register_setting('kurage', 'kurage_text_1');
register_setting('kurage', 'kurage_text_3');

register_setting()はフォームの値をオプションにマッピングし自動更新出来るように設定します。

この例では、POSTリクエストのactionupdateであり、
管理ページのスラグ(option_page)がkurageの時、

リクエスト中にkurage_text_1kurage_text_3が入っていたらその名前と値のセットを自動的にオプションにたいして更新させますよ、
っていう設定です。

なのでkurage_text_2はリクエストで渡したものの、
オプションには追加されず無視されました。

その様子をoptions.phpのある部分(update_option()が実行されている箇所)にブレークポイントを張って調べてみましょう。

Watch式に注目してください。

kurage_text_1の情報

kurage_text_3の情報

Settings

Settingsについてです。
この機能は、管理画面の入力フィールドを描画するための機能なようで、
描画する場所に張る関数と、描画するための設定を登録する関数があります。

描画する場所に張る関数は

  • do_settings_fields(), do_settings_sections()

描画するための設定を登録する関数

  • add_settings_field(), add_settings_section()

これらの関数は引数に何を渡せばいいのか非常に分かりづらかったです。
最初にざっくり概念を知ってないと引数が多すぎてどれがどの値なのか混乱します。

管理画面には、管理画面を識別するスラグ(今回の例ではkurageがあります)。
設定画面には、値を入力するフィールドを記述しますが、セクションでそれらを分割することが出来ます。
ちょっと分かりにくいので画像にするとこんな感じです。

まず管理ページの(kurage)があって、
その下に3つのセクションがあって、それぞれID(今回はそれぞれnumber, alfabet, symbol)を付けてます(任意につけることが出来ます)。
さらにそのセクション下に入力フィールド(それぞれテキストフィールド3つ)を追加している状態です。

つまり、

管理ページスラグ -> セクション -> フィールド

という階層構造になってます。

この構造を作るには、セクションの登録にadd_settings_section()を、
フィールドの登録にadd_settings_field()を使います。

do_settings_sections(管理ページスラグ)を使って3つのセクションをまとめて描画します。
do_settings_fields(管理ページスラグ, セクションID)を使って対象のセクションにあるフィールドをまとめて描画します。

では今回の例を再現してみましょう。

add_action('admin_menu', function(){

    function showPage()
    {
        ?>

        <div class="wrap">

            <h2>テキストの追加</h2>

            <form action="options.php" method="POST">

                <?php settings_fields('kurage') ?>

                <?php do_settings_sections('kurage') ?>

                <?php submit_button() ?>

        <?php
    }

    add_menu_page(
        'クラゲ管理画面',
        'クラゲメニュー設定',
        'manage_options',
        'kurage',
        function()
        {
            showPage();
        }
    );

});

add_action('admin_init', function(){

    $callback = fn() => print('<input type="text" />');

    // セクションの設定
    add_settings_section('number', '数値の項目', null, 'kurage');
    add_settings_section('alfabet', 'アルファベットの項目', null, 'kurage');
    add_settings_section('symbol', '記号の項目', null, 'kurage');

    // numberセクションに追加するフィールドの設定
    add_settings_field('one', 'すうじの1', $callback, 'kurage', 'number');
    add_settings_field('two', 'すうじの2', $callback, 'kurage', 'number');
    add_settings_field('three', 'すうじの3', $callback, 'kurage', 'number');

    // alfabetセクションに追加するフィールドの設定
    add_settings_field('a', 'あるふぁべっとのA', $callback, 'kurage', 'alfabet');
    add_settings_field('b', 'あるふぁべっとのB', $callback, 'kurage', 'alfabet');
    add_settings_field('c', 'あるふぁべっとのC', $callback, 'kurage', 'alfabet');

    // symbolセクションに追加するフィールドの設定
    add_settings_field('plus', '記号の +', $callback, 'kurage', 'symbol');
    add_settings_field('minus', '記号の -', $callback, 'kurage', 'symbol');
    add_settings_field('dollar', '記号の $', $callback, 'kurage', 'symbol');

});

以下が結果です。

add_settings_section()はセクションを登録します。

add_settings_section('number', '数値の項目', null, 'kurage');

第一引数がセクションのIDとなるものでnumberを指定しました(名前は任意です。)。
第四引数は管理ページのスラグでkurageを指定しました。

これで

kurage -> number

という階層のセクションを登録しました。
あとalfabetsymbolも同様にセクションを登録していきます。

第二引数はラベルです。
do_settings_sections()によってセクションごとに描画されます。

次にadd_settings_field()でフィールドを登録します。

add_settings_field('one', 'すうじの1', $callback, 'kurage', 'number');

第一引数がセクションのIDで、
第四引数が管理画面のスラグ、
第五引数がセクションのIDです。

これで

kurage -> number -> one

という階層のフィールドを登録しました。

第三引数はINPUT要素などを描画するコールバック関数を指定します。
今回は面倒なので全部未記入のテキストフィールドを返すコールバック関数を指定しました。

そして描画するにはdo_settings_sections()を使います。

do_settings_sections('kurage')

引数に管理画面のスラグを渡すことで、その管理画面に属する全てのセクション、フィールドをまとめて描画します。

セクション単位の描画

全セクションの描画をしましたが、セクション単位の描画もできはします。
もしdo_settings_sections('kurage')の部分をdo_settings_fields()に置き換えるとどうなるでしょう。

function showPage()
{
    ?>

    <div class="wrap">

        <h2>テキストの追加</h2>

        <form action="options.php" method="POST">

            <?php settings_fields('kurage') ?>

            <table>
                <?php do_settings_fields('kurage', 'alfabet') ?>
            </table>

            <?php submit_button() ?>

    <?php
}

今回の例はdo_settings_fields('kurage', 'alfabet')を使いました。
管理画面(kurage)のセクション(alfabet)にあるフィールド一覧を描画します。

注意しないといけないのは、この関数はTABLEタグを描画しません。
いきなりテーブルの行をフィールド数の分描画します。
そのため自分でTABLEで囲んでやる必要があります。

そして本来do_settings_fields()do_settings_sections()によって内部的に呼び出されるもので直接呼び出すものでもなさそうです。
ちなみにdo_settings_sections()ではTABLEに追加されるクラス(CSS)もあるのです。

フィールドの作成

また、以下のようにフィールドを作成することが出来ます。

add_action('admin_menu', function(){

    function showPage()
    {
        ?>

        <div class="wrap">

            <h2>テキストの追加</h2>

            <form action="options.php" method="POST">

                <?php settings_fields('kurage') ?>

                <table>
                    <?php do_settings_sections('kurage') ?>
                </table>

                <?php submit_button() ?>

        <?php
    }

    add_menu_page(
        'クラゲ管理画面',
        'クラゲメニュー設定',
        'manage_options',
        'kurage',
        function()
        {
            showPage();
        }
    );

});

add_action('admin_init', function(){

    $callback = fn($args) => printf('<input type="text" name="%s" value="%s"/>', esc_attr($args[0]), esc_attr($args[1]));

    // セクションの設定
    add_settings_section('number', '数値の項目', null, 'kurage');

    // numberセクションに追加するフィールドの設定
    add_settings_field('one', 'すうじの1', $callback, 'kurage', 'number', ['one', 111]);
    add_settings_field('two', 'すうじの2', $callback, 'kurage', 'number', ['two', 222]);
    add_settings_field('three', 'すうじの3', $callback, 'kurage', 'number', ['three', 333]);

});

add_settings_field()の第六引数ではコールバックに渡す引数を指定することが出来ます。

add_settings_field('one', 'すうじの1', $callback, 'kurage', 'number', ['one', 111]);

一行で長いですが、コールバックではテキストフィールドにnamevalueを指定出来るようにしました。

fn($args) => printf('<input type="text" name="%s" value="%s"/>', esc_attr($args[0]), esc_attr($args[1]));

これで入力済のフィールドを描画出来るようになりました。

本体の設定ページに追加

ところでWordPress本体の設定画面がありますよね。
例えば設定からメディアを開いてみてください。
画像サイズの設定などの項目があります。

この管理画面は/wp-admin/options-media.phpで実装されています。
そのソースコードの一部を見ると

</tr>

    <?php do_settings_fields( 'media', 'uploads' ); ?>
</table>
<?php endif; ?>

<?php do_settings_sections( 'media' ); ?>

<?php submit_button(); ?>

などのように定義されています!
ということは、本体の設定画面にセクションやフィールドを追加出来るということですね。

add_action('admin_init', function(){

    // media の uploads セクションに追加
    add_settings_field('kurage-uploader', 'クラゲアップローダー', fn() => print('... 省略'), 'media', 'uploads');

    // media にセクションごと追加
    add_settings_section('kurage-section', 'クラゲセクション', null, 'media');
    add_settings_field('kurage-a', 'クラゲA', fn() => print('AAA'), 'media', 'kurage-section');
    add_settings_field('kurage-b', 'クラゲB', fn() => print('BBB'), 'media', 'kurage-section');
    add_settings_field('kurage-c', 'クラゲC', fn() => print('CCC'), 'media', 'kurage-section');

});

これで目的の場所にフィールドを追加出来るようになりました。

certificate Docker Gutenberg Hyper-V openssl PHP React ReduxToolkit REST ubuntu WordPress オレオレ認証局 フレームワーク