2026年5月20日
2026年5月20日
テーマオプションページを作る方法|Settings APIで設定画面を追加して値を保存・表示する
フッターの著作権表示やSNSのURL、テーマの基本色などを、コードを書き換えずに管理画面から変えられるようにするのがテーマオプションページです。WordPress の Settings API を使うと、フォームの nonce 確認や保存処理を WordPress に任せられ、自分で書くのは「どの項目を出すか」と「どう検証するか」だけになります。
この記事の関数と引数は developer.wordpress.org の Settings API・Administration Menus のドキュメントと WordPress 6.9 のソースコードで2026年10月時点の内容を確認しています。クラシックテーマ(PHP テンプレートのテーマ)向けの手順です。
先に決めること: 設定ページか、カスタマイザーか
| 方法 | 向いているもの | 備考 |
|---|---|---|
| 設定ページ(この記事) | 文字列・URL・ON/OFF など、見た目に直接出ないものも含む設定 | 「外観」や「設定」の下に独自の画面を作る |
| カスタマイザー | 色・ロゴ・レイアウトなど、プレビューしながら変えたい設定 | 「外観」→「カスタマイズ」。値は get_theme_mod() で取得 |
| サイトエディター | ブロックテーマの色・文字・余白 | theme.json と「スタイル」で設定。PHP の設定ページは不要なことが多い |
カスタマイザーで作る場合は カスタマイザーAPIの使い方 を参照してください。ここでは設定ページを作ります。
完成形の構成
- メニュー: 「外観」→「テーマ設定」
- 保存先:
wp_optionsテーブルのmytheme_options(1つのオプションに配列でまとめて保存) - 項目: フッターの文言、X(旧Twitter)の URL、基本色
以下のコードは、テーマの functions.php か、functions.php から読み込む別ファイル(例: inc/theme-options.php)に書きます。
手順1: 初期値と取得用の関数を用意する
<?php
// 設定の初期値
function mytheme_default_options() {
return array(
'footer_text' => '© ' . wp_date( 'Y' ) . ' ' . get_bloginfo( 'name' ),
'x_url' => '',
'primary_color' => '#2271b1',
);
}
// 保存値と初期値をまとめて返す(未保存の項目は初期値になる)
function mytheme_get_option( $key ) {
$options = wp_parse_args( get_option( 'mytheme_options', array() ), mytheme_default_options() );
return isset( $options[ $key ] ) ? $options[ $key ] : '';
}
register_setting() にも default を渡せますが、その初期値が効くのは register_setting() を実行したリクエストの中だけです。登録を admin_init で行う場合、サイトの表側では効かないため、上のような取得関数で初期値を補います。
手順2: メニューに設定ページを追加する
<?php
function mytheme_add_options_page() {
add_theme_page(
'テーマ設定', // ページの <title> と見出し
'テーマ設定', // メニューに出る名前
'edit_theme_options', // 表示に必要な権限
'mytheme-options', // ページのスラッグ(URL の ?page= の値)
'mytheme_render_options_page' // 画面を出力する関数
);
}
add_action( 'admin_menu', 'mytheme_add_options_page' );
add_theme_page()は「外観」の下にページを追加します。中身はadd_submenu_page( 'themes.php', … )と同じです。- 権限
edit_theme_optionsは、既定では管理者が持っています。「外観」→「メニュー」などと同じ権限です。 - 「設定」の下に置くなら
add_options_page()、メニューの最上位に独立させるならadd_menu_page()を使います。add_menu_page()の第7引数(表示位置)で、既定のメニューは「外観」が 60、「プラグイン」が 65 です。同じ数字を指定しても WordPress がずらして並べますが、61のように空いている数字を使うと位置がわかりやすくなります。
手順3: Settings API で項目を登録する
<?php
function mytheme_register_settings() {
register_setting(
'mytheme_options_group', // オプショングループ(フォームの settings_fields() で使う)
'mytheme_options', // wp_options に保存されるオプション名
array(
'type' => 'array',
'sanitize_callback' => 'mytheme_sanitize_options',
)
);
add_settings_section(
'mytheme_section_general',
'基本設定',
'__return_false', // セクションの説明は出さない
'mytheme-options' // 手順2のページスラッグ
);
add_settings_field(
'mytheme_footer_text',
'フッターの文言',
'mytheme_field_footer_text',
'mytheme-options',
'mytheme_section_general',
array( 'label_for' => 'mytheme_footer_text' )
);
add_settings_field(
'mytheme_x_url',
'X(旧Twitter)のURL',
'mytheme_field_x_url',
'mytheme-options',
'mytheme_section_general',
array( 'label_for' => 'mytheme_x_url' )
);
add_settings_field(
'mytheme_primary_color',
'基本色',
'mytheme_field_primary_color',
'mytheme-options',
'mytheme_section_general',
array( 'label_for' => 'mytheme_primary_color' )
);
}
add_action( 'admin_init', 'mytheme_register_settings' );
label_for を指定すると、項目名が入力欄の <label for="…"> になり、項目名をクリックすると入力欄にカーソルが移ります。値は入力欄の id と同じにします。
手順4: 入力欄を出力する関数を書く
入力欄の name は オプション名[キー] にします。こうすると、すべての項目が mytheme_options という1つの配列として送信・保存されます。
<?php
function mytheme_field_footer_text() {
printf(
'<input type="text" id="mytheme_footer_text" name="mytheme_options[footer_text]" value="%s" class="regular-text">',
esc_attr( mytheme_get_option( 'footer_text' ) )
);
echo '<p class="description">フッターに表示する著作権表示などの文言です。HTML は使えません。</p>';
}
function mytheme_field_x_url() {
printf(
'<input type="url" id="mytheme_x_url" name="mytheme_options[x_url]" value="%s" class="regular-text" placeholder="https://x.com/your-account">',
esc_attr( mytheme_get_option( 'x_url' ) )
);
}
function mytheme_field_primary_color() {
printf(
'<input type="color" id="mytheme_primary_color" name="mytheme_options[primary_color]" value="%s">',
esc_attr( mytheme_get_option( 'primary_color' ) )
);
}
手順5: 設定ページの画面を出力する
<?php
function mytheme_render_options_page() {
if ( ! current_user_can( 'edit_theme_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<?php settings_errors(); ?>
<form action="options.php" method="post">
<?php
settings_fields( 'mytheme_options_group' ); // nonce と隠しフィールド
do_settings_sections( 'mytheme-options' ); // 手順3で登録したセクションと項目
submit_button( '設定を保存' );
?>
</form>
</div>
<?php
}
- フォームの送信先は
options.phpです。保存処理(権限と nonce の確認、サニタイズ、update_option())は WordPress が行い、終わると元の画面に戻ります。 - 「設定を保存しました。」の通知は、「設定」の下のページなら WordPress が自動で表示しますが、「外観」の下や最上位メニューのページでは表示されません。そのため
settings_errors()を呼んでいます。「設定」の下(add_options_page())に置く場合は、二重に表示されるのでsettings_errors()は不要です。
手順6: 保存前に値を検証する(サニタイズ)
register_setting() の sanitize_callback に渡した関数が、保存の直前に呼ばれます。送られてきた値を項目ごとに検証し、許可した値だけを返します。
<?php
function mytheme_sanitize_options( $input ) {
$defaults = mytheme_default_options();
$output = array();
if ( ! is_array( $input ) ) {
return $defaults;
}
$output['footer_text'] = isset( $input['footer_text'] )
? sanitize_text_field( $input['footer_text'] )
: $defaults['footer_text'];
$output['x_url'] = isset( $input['x_url'] )
? esc_url_raw( $input['x_url'] )
: '';
$color = isset( $input['primary_color'] ) ? sanitize_hex_color( $input['primary_color'] ) : '';
if ( ! $color ) {
$color = $defaults['primary_color'];
add_settings_error( 'mytheme_options', 'invalid_color', '基本色の値が正しくないため、初期値に戻しました。' );
}
$output['primary_color'] = $color;
return $output;
}
sanitize_text_field()はタグや改行を取り除きます。改行を残したい項目にはsanitize_textarea_field()を使います。esc_url_raw()はhttp・httpsなどの許可されたプロトコル以外の URL を空にします。sanitize_hex_color()は#fffや#2271b1の形式以外を受け付けません。add_settings_error()で登録したメッセージは、手順5のsettings_errors()で画面に表示されます。
手順7: テーマで設定値を使う
footer.php などのテンプレートでは、手順1の取得関数で値を読み、出力の直前にエスケープします。
<?php
// footer.php など
$x_url = mytheme_get_option( 'x_url' );
?>
<footer class="site-footer">
<p><?php echo esc_html( mytheme_get_option( 'footer_text' ) ); ?></p>
<?php if ( $x_url ) : ?>
<a href="<?php echo esc_url( $x_url ); ?>" rel="noopener">X</a>
<?php endif; ?>
</footer>
基本色は CSS 変数として <head> に出力しておくと、テーマの CSS から var(--mytheme-primary) で使えます。
<?php
function mytheme_output_primary_color() {
$color = sanitize_hex_color( mytheme_get_option( 'primary_color' ) );
if ( $color ) {
echo '<style id="mytheme-options-css">:root{--mytheme-primary:' . esc_html( $color ) . ';}</style>' . "\n";
}
}
add_action( 'wp_head', 'mytheme_output_primary_color' );
動作を確認する
- 管理画面の「外観」→「テーマ設定」を開き、値を入れて「設定を保存」を押す
- 画面上部に「設定を保存しました。」と表示されることを確認する
- サイトの表側でフッターと色が変わっていることを確認する
保存された値は WP-CLI でも確認できます。
wp option get mytheme_options --format=json
注意点
- 権限の確認は2か所で行われます。
add_theme_page()の権限でメニューと画面の表示が制限され、保存時にはoptions.phpが権限と nonce を確認します。update_option()を自前のフォーム処理で呼ぶ場合は、current_user_can()とcheck_admin_referer()を自分で書く必要があり、漏れやすいので Settings API を使う方が安全です。 - 既定では、
options.phpへの保存に必要な権限はmanage_optionsです。ページの表示権限をedit_theme_optionsにした場合でも、管理者以外が保存すると権限エラーになります。管理者以外にも保存させたいときはoption_page_capability_mytheme_options_groupフィルターでedit_theme_optionsを返します。 - テーマを切り替えても
mytheme_optionsはwp_optionsに残ります。不要になったらwp option delete mytheme_optionsで削除できます。
<?php
// 管理者以外(edit_theme_options を持つユーザー)にも保存を許可する場合
function mytheme_options_capability() {
return 'edit_theme_options';
}
add_filter( 'option_page_capability_mytheme_options_group', 'mytheme_options_capability' );
まとめ
add_theme_page()で「外観」の下に設定ページを追加するregister_setting()・add_settings_section()・add_settings_field()で項目を登録し、name="オプション名[キー]"で1つの配列に保存する- フォームは
options.phpに送り、settings_fields()・do_settings_sections()・submit_button()で組み立てる - 値は
sanitize_callbackで検証し、表示するときはesc_html()・esc_url()でエスケープする - 表側の初期値は
register_setting()のdefaultに頼らず、取得関数で補う