2026年9月21日

2026年9月21日

WordPress Settings APIで管理画面設定ページを実装する方法

はじめに

WordPress Settings APIは、プラグインや子テーマの設定ページを管理画面に安全に実装するための公式フレームワークです。nonceの自動生成・設定の保存・エラー表示など、設定ページに必要な機能が組み込まれており、セキュリティと一貫したUIを同時に実現できます。本記事では、設定メニューの追加から各フィールドの実装まで段階的に解説します。

症状・原因

  • プラグインの設定ページを手動で実装しているが、nonceの処理や保存ロジックが複雑になっている
  • 設定ページのUIがWordPress標準のデザインと一致せず、管理画面で違和感がある
  • 複数の設定セクションとフィールドを整理された形で管理する方法がわからない

解決手順

ステップ1:add_options_page()で管理メニューを追加する

<?php
/**
 * 管理画面メニューの追加
 */
add_action( 'admin_menu', 'my_plugin_add_menu' );

function my_plugin_add_menu() {
    // 「設定」メニューのサブページとして追加する
    add_options_page(
        'My Plugin 設定',     // ページタイトル(<title>タグ)
        'My Plugin',          // メニューに表示されるラベル
        'manage_options',     // このページを表示できる権限
        'my-plugin-settings', // メニュースラッグ(URLの一部)
        'my_plugin_settings_page' // 設定ページを出力するコールバック関数
    );

    // カスタムメニューに追加する場合は add_menu_page() を使用
    // add_menu_page(
    //     'My Plugin',
    //     'My Plugin',
    //     'manage_options',
    //     'my-plugin',
    //     'my_plugin_settings_page',
    //     'dashicons-admin-plugins',
    //     80
    // );

    // サブメニューを追加する場合
    // add_submenu_page(
    //     'my-plugin',            // 親メニューのスラッグ
    //     'My Plugin 詳細設定',
    //     '詳細設定',
    //     'manage_options',
    //     'my-plugin-advanced',
    //     'my_plugin_advanced_page'
    // );
}

ステップ2:register_setting()でサニタイズコールバックを登録する

<?php
/**
 * 設定の登録(admin_init フックで実行)
 */
add_action( 'admin_init', 'my_plugin_register_settings' );

function my_plugin_register_settings() {

    // メイングループの設定を登録
    register_setting(
        'my_plugin_options_group',   // オプショングループ名(settings_fields() で使用)
        'my_plugin_general',         // オプション名(wp_options に保存されるキー)
        array(
            'sanitize_callback' => 'my_plugin_sanitize_general',
            'default'           => array(
                'site_title'     => '',
                'enable_logging' => false,
                'log_level'      => 'error',
            ),
        )
    );

    // 詳細設定グループ
    register_setting(
        'my_plugin_options_group',
        'my_plugin_advanced',
        array(
            'sanitize_callback' => 'my_plugin_sanitize_advanced',
        )
    );
}

/**
 * 一般設定のサニタイズ
 */
function my_plugin_sanitize_general( $input ) {
    $output = array();
    $output['site_title']     = sanitize_text_field( $input['site_title'] ?? '' );
    $output['enable_logging'] = ! empty( $input['enable_logging'] );
    $allowed_levels           = array( 'debug', 'info', 'warning', 'error' );
    $output['log_level']      = in_array( $input['log_level'] ?? '', $allowed_levels, true )
        ? $input['log_level']
        : 'error';
    return $output;
}

ステップ3:add_settings_section()でセクションを追加する

<?php
/**
 * 設定セクションの追加
 * ※ admin_init フック内で register_setting() と一緒に実行する
 */
function my_plugin_register_settings() {
    // ... register_setting() の後に続けて記述 ...

    // === 一般設定セクション ===
    add_settings_section(
        'my_plugin_general_section',          // セクションID
        '一般設定',                            // セクションのタイトル
        'my_plugin_general_section_callback', // セクション説明文のコールバック
        'my-plugin-settings'                  // このセクションが属するページスラッグ
    );

    // === 詳細設定セクション ===
    add_settings_section(
        'my_plugin_advanced_section',
        '詳細設定',
        'my_plugin_advanced_section_callback',
        'my-plugin-settings'
    );
}

/**
 * セクション説明文の出力コールバック
 */
function my_plugin_general_section_callback() {
    echo '<p>プラグインの基本的な動作を設定します。</p>';
}

function my_plugin_advanced_section_callback() {
    echo '<p>上級者向けの詳細設定です。変更は慎重に行ってください。</p>';
}

ステップ4:add_settings_field()でフィールドを追加する

<?php
/**
 * 設定フィールドの追加
 */
function my_plugin_register_settings() {
    // ... セクション登録の後に続けて記述 ...

    // テキストフィールド
    add_settings_field(
        'my_plugin_site_title',          // フィールドID
        'サイト表示名',                   // フィールドラベル
        'my_plugin_field_site_title',    // フィールドHTMLを出力するコールバック
        'my-plugin-settings',            // ページスラッグ
        'my_plugin_general_section',     // 属するセクションID
        array( 'label_for' => 'my_plugin_site_title' ) // <label>のfor属性と紐付ける
    );

    // チェックボックス
    add_settings_field(
        'my_plugin_enable_logging',
        'ログ記録',
        'my_plugin_field_enable_logging',
        'my-plugin-settings',
        'my_plugin_general_section'
    );

    // セレクトボックス
    add_settings_field(
        'my_plugin_log_level',
        'ログレベル',
        'my_plugin_field_log_level',
        'my-plugin-settings',
        'my_plugin_general_section'
    );
}

/**
 * テキストフィールドのコールバック
 */
function my_plugin_field_site_title() {
    $options = get_option( 'my_plugin_general', array() );
    $value   = isset( $options['site_title'] ) ? $options['site_title'] : '';
    ?>
    <input type="text"
           id="my_plugin_site_title"
           name="my_plugin_general[site_title]"
           value="<?php echo esc_attr( $value ); ?>"
           class="regular-text"
           placeholder="例:ワードプレス博士">
    <p class="description">フロントエンドに表示されるサイト名です。</p>
    <?php
}

/**
 * チェックボックスのコールバック
 */
function my_plugin_field_enable_logging() {
    $options = get_option( 'my_plugin_general', array() );
    $checked = ! empty( $options['enable_logging'] );
    ?>
    <label>
        <input type="checkbox"
               name="my_plugin_general[enable_logging]"
               value="1"
               <?php checked( $checked ); ?>>
        ログ記録を有効にする
    </label>
    <p class="description">有効にするとデバッグログが記録されます。</p>
    <?php
}

/**
 * セレクトボックスのコールバック
 */
function my_plugin_field_log_level() {
    $options  = get_option( 'my_plugin_general', array() );
    $current  = isset( $options['log_level'] ) ? $options['log_level'] : 'error';
    $choices  = array(
        'debug'   => 'デバッグ(すべて記録)',
        'info'    => '情報',
        'warning' => '警告',
        'error'   => 'エラーのみ',
    );
    ?>
    <select id="my_plugin_log_level" name="my_plugin_general[log_level]">
        <?php foreach ( $choices as $value => $label ) : ?>
            <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $current, $value ); ?>>
                <?php echo esc_html( $label ); ?>
            </option>
        <?php endforeach; ?>
    </select>
    <?php
}

ステップ5:settings_fields/do_settings_sectionsとsettings_errorsで設定フォームを完成させる

<?php
/**
 * 設定ページのHTMLを出力するコールバック
 */
function my_plugin_settings_page() {
    // 権限チェック
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die( __( 'このページへのアクセス権限がありません。', 'my-plugin' ) );
    }
    ?>
    <div class="wrap">
        <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>

        <?php
        // 設定保存後のメッセージを表示する
        // 'updated' クラスの成功メッセージと 'error' クラスのエラーメッセージを自動出力
        settings_errors( 'my_plugin_options_group' );
        ?>

        <form method="post" action="options.php">
            <?php
            /**
             * settings_fields(): 以下を自動出力する
             * - hidden フィールド(option_page, action)
             * - nonce フィールド(CSRF対策)
             * - _wp_http_referer フィールド
             */
            settings_fields( 'my_plugin_options_group' );

            /**
             * do_settings_sections(): 指定ページの全セクション・全フィールドを出力する
             * - <table> 形式で各フィールドが整列して表示される
             */
            do_settings_sections( 'my-plugin-settings' );

            // 送信ボタンを出力(WordPressスタイルに準拠)
            submit_button( '設定を保存' );
            ?>
        </form>

        <?php
        // カスタムエラーメッセージの追加例(settings_errors() で表示される)
        // add_settings_error(
        //     'my_plugin_options_group',
        //     'my_plugin_error',
        //     'APIキーが無効です。正しいキーを入力してください。',
        //     'error'
        // );
        ?>
    </div>
    <?php
}

注意事項

  • settings_fields()は必須: フォーム内でsettings_fields()を呼び忘れると、nonceが生成されず設定が保存されません
  • オプショングループ名の一致: register_setting()・settings_fields()・do_settings_sections()で使用するグループ名とページスラッグを一致させてください
  • do_settings_sections()の引数: add_settings_section()・add_settings_field()の第4引数(ページスラッグ)と同じ文字列を渡す必要があります
  • カスタムフォームレイアウト: do_settings_sections()の代わりにdo_settings_fields()を使うと、テーブルレイアウトを使わずカスタムレイアウトで各フィールドを出力できます

まとめ

Settings APIは「登録→セクション追加→フィールド追加→フォーム出力」の4ステップで、安全で標準的な管理画面設定ページを実装できます。settings_fields()によるnonce自動処理とdo_settings_sections()による一括出力により、手動実装に比べてコード量を大幅に削減できます。関連記事:WordPress管理画面ダッシュボードにカスタムウィジェットを追加する方法

お気軽にご相談ください

お見積りへ お問い合わせへ
▲