こんにちわ、わかっち (@wakatchi_tech) です。

WordPressで開発したサイトを運営していると、サイト独自の設定を保存したり、運用しながら設定を変更したいことがあります。

前回、前々回の記事では、WordPressのトップメニューやサブメニューの追加方法をご紹介しました。

WordPressに独自の管理メニューを追加する① トップメニューの追加

WordPress の管理画面に独自のトップメニューを追加する方法を、add_menu_page() の引数・アイコン・表示位置の決め方までコード付きで解説します。add_submenu_page との…

WordPressに独自のサブメニューの追加する

add_submenu_page()でWordPress管理画面にサブメニューを追加する方法をコード例付きで解説。新規メニューの下に足す場合と、設定・ツールなど既存メニューに足す場合、両…

この記事では、追加したサブメニューで、実際に値を保存したり、保存した値を取得する方法をご紹介します。

この記事は次のような方にお勧めです

  • WordPressのサイト開発者で、サイト全体の設定をWordPressの管理メニューで設定したい人
  • WordPressのテーマやプラグインの開発者

add_settings_section()・add_settings_field()の実装で迷いやすいポイントを早見表にまとめました。詳細は本文中の該当セクションで解説しています。

関数・引数迷いやすいポイント
add_settings_section() の $callbackセクション見出しとフィールドの間に表示したい説明文などを、この関数の中で echo する(returnではない)
add_settings_field() の $callback実際に画面へ出す <input> などのHTMLを、この関数の中で echo する。保存済みの値を表示するには get_option() と組み合わせる
$page 引数add_settings_section() / add_settings_field() / do_settings_sections() で同じスラッグに揃える必要がある
add_settings_field() の $args の label_for指定するとタイトルが <label> 要素でラップされ、その値が <label> の for 属性に設定される

管理メニューのコード例

本記事では、WordPressの管理メニューに設定を保存する画面を作る方法をご紹介します。

トップメニューの画面に一つだけフィールドを設けて、名前を保存してみます。

上記の画面は、下記のソースコードでWordPressに組み込むことが可能です。
function.phpやCode Snippetsプラグインなどを使ってそのままコピペしてみてください。

<?php
add_action(
	'admin_menu',
	function(){
		// トップメニューを追加
		add_menu_page(
			'管理メニュータイトル'
			, 'テスト用トップメニュー'
			, 'manage_options' 
			, 'top_menu' 
			, 'render_menu_contents' // トップメニューの描画関数
			,'dashicons-networking'
			,0
		);

		// セクションを追加
		add_settings_section(
			'top_menu_section'
			,'セクション'
			,'render_section' //セクションの描画関数
			,'top_menu'
		);
		
		// フィールドを追加
		add_settings_field(
			'key_name'
			,'名前'
			,'render_name_field'  // フィールドの描画関数
			,'top_menu'
			,"top_menu_section"
			,array( 'label_for' => 'key_name' )
		);
		
		// フィールドをグループに登録
		register_setting(
			"top_menu_group"
			,'key_name'
		);
    }
);

// セクションを描画する
function render_section( $args ) {
	?>
		セクションのコンテンツを記載します
		<hr>
	<?
}

// トップメニュー画面を描画する
function render_menu_contents() {
	?>
	<div class = "wrap">
		<h1>テスト用オプション設定</h1>
		<form method = "post" action = "options.php" >
			<?php
 				settings_fields( 'top_menu_group' );  
				do_settings_sections( 'top_menu' ); 
				submit_button( '設定を更新' , 'primary' );
			?>
		</form>
	</div>
	<?
}

// フィールドを描画する
function render_name_field( $args ){
	?>
	<input
		   type="text"
		   name='<?= 'key_name' ?>'
		   value='<?= esc_attr( get_option( 'key_name' ) ) ?>'
			/>
	<?
}

トップメニューの画面追加に加えて、セクションやフィールドなど多くの処理が記載されています。

Settings APIとは

設定画面の作り方を説明する前に、WordPressのSettings APIを理解しておきましょう。

Settings APIとは、WordPress 2.7以降から導入されたもので、設定フォームを含む管理ページを半自動的に管理できます。設定ページ、それらのページ内のセクション、およびセクション内のフィールドを定義できます。

新しい設定ページをその中のセクションやフィールドとともに登録できます。既存の設定ページ内に新しい設定セクションまたはフィールドを登録することで、既存の設定ページを追加することもできます。

Settings API

登録・登録解除の設定

  • register_setting()
  • unregister_setting()

フィールド・セクションの追加

  • add_settings_field()
  • add_settings_section()

オプション・フォームの描画

  • settings_fields()
  • do_settings_sections()
  • do_settings_sections()

エラー

  • add_settings_error()
  • get_settings_errors()
  • settings_errors()

この記事では、Settings APIを使った管理メニューに画面作成をご紹介します。

詳細は以下の公式サイトをご覧ください。

Settings – Common APIs Handbook | Developer.WordPress.org

Overview The Settings API, added in WordPress 2.7, allows admin pages containing settings forms to be managed semi-automatically. It lets…

管理メニューに画面を組み込む手順

WordPressの管理メニューに画面を組み込むには、Settings APIを使い手順に従って進める必要があります。

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

add_menu_page()で管理メニューのトップメニューに画面を追加します。

もちろん、さらにサブメニューを追加しても構いません。

<?php
// トップメニューを追加
add_menu_page(
		'管理メニュータイトル'
		, 'テスト用トップメニュー'
		, 'manage_options' 
		, BASE_SLUG 
		, 'render_menu_contents' // トップメニューの描画関数
		,'dashicons-networking'
		,0
);

// トップメニュー画面を描画する
function render_menu_contents() {
	?>
	<?
}

画面は、Settings APIを使ってセクションやフィールドを描画します。詳細は「セクションとフィールドを描画する」でご説明します。

また、トップメニューやサブメニューの追加は、過去の記事をご覧ください。

WordPressに独自の管理メニューを追加する① トップメニューの追加

WordPress の管理画面に独自のトップメニューを追加する方法を、add_menu_page() の引数・アイコン・表示位置の決め方までコード付きで解説します。add_submenu_page との…

管理メニューに設定セクションを追加する

add_settings_section()で、管理メニューに設定セクションを追加します。

管理メニュー内に複数のセクションが登録できます。1画面内に多くの設定項目がある場合は、セクションごとにグループしても良いでしょう。

今回の例ではセクションは一つだけ設定しています。

<?php
// セクションを追加
add_settings_section(
		'top_menu_section'
		,'セクション'
		,'render_section' //セクションの描画関数
		,BASE_SLUG
);

// セクションを描画する
function render_section( $args ) {
	?>
		セクションのコンテンツを記載します
		<hr>
	<?
}

add_settings_section()は、設定ページに新しいセクションを追加します。これを使用して、管理ページの新しい設定セクションを定義します。

do_settings_sections()を使用して、管理メニューのコールバック関数に設定セクションを表示します。

また、add_settings_field()を使用して設定フィールドをセクションに追加します。

add_settings_section()の引数

  • $id(必須)
    セクションを識別するためのスラッグ名。
    タグのid属性で使用されます。
  • $title(必須)
    セクションの書式設定されたタイトル。セクションの見出しとして表示されます。
  • $callback(必須)
    セクションの先頭 (見出しとフィールドの間) のコンテンツを描画する関数。
  • $page(必須)
    セクションを表示する設定ページのスラッグ名。組み込み済みのスラッグとして、'general'や'reading'、'writing'、'discussion'、'media'があります。
  • $args(任意)
    セクションの生成に使用されます。
    • before_section
      セクションの HTML 出力の先頭に追加する HTML コンテンツです。
    • after_section
      セクションの HTML 出力に追加する HTML コンテンツです。
    • section_class
      セクションに使用するクラス名です。

設定フィールドを追加する

add_settings_field()で、画面にフィールドを追加します。

<?php
// フィールドを追加
add_settings_field(
		OPTION_KEY_NAME
		,'名前'
		,'render_name_field'  // フィールドの描画関数
		,BASE_SLUG
		,"top_menu_section"
		,array( 'label_for' => OPTION_KEY_NAME )
);

// フィールドを描画する
function render_name_field( $args ){
	?>
	<input
		   type="text"
		   name='<?= OPTION_KEY_NAME ?>'
		   value='<?= esc_attr( get_option( OPTION_KEY_NAME ) ) ?>'
			/>
	<?
}

設定した値がWordPressのデータベースに保存され、次に画面を開いたときにその値が表示されるようになります。

わかっち

Inputタグのname属性に指定した文字列と、その文字列でget_option関数で取得した値をvalue属性に設定しているのが重要なポイントだよ

add_settings_field()は、設定ページのセクションに新しいフィールドを追加します。

これを使用して、設定ページ内の設定セクションの一部として表示される設定フィールドを定義します。フィールドはdo_settings_sections()を使用して表示されます。

add_settings_field()の引数

  • $id(必須)
    フィールドを識別するためのスラッグ名。
    タグのid属性で使用されます。
  • $title(必須)
    フィールドの書式設定されたタイトル。
    出力時にフィールドのラベルとして表示されます。
  • $callback(必須)
    フィールドに必要なフォーム入力を描画する関数です。
    この関数ではその出力をechoする必要があります。
  • $page(必須)
    セクション (一般、読み取り、書き込みなど) を表示する設定ページのスラッグ名。
  • $section(任意)
    ボックスを表示する設定ページのセクションのスラッグ名。
  • $args(任意)
    コールバック関数に渡される追加の引数。
    • label_for
      指定すると、設定タイトルが<label>要素でラップされ、<for>属性にこの値が設定されます
    • class
      <tr>フィールドの出力時に要素に追加される CSS クラス。

設定を登録する

register_setting()でフィールドグループに登録します。

register_setting()を実行しないと、フィールドの値が自動的に保存および更新されない点に注意してください。

<?php
// フィールドグループを設定
register_setting(
		"top_menu_group"
		,OPTION_KEY_NAME
);

register_setting()は、設定とそのデータを登録します。

register_setting()の引数

  • $option_group(必須)
    設定グループ名。
    許可されたオプション キー名に対応する必要があります。
  • $option_name(必須)
    サニタイズして保存するオプションの名前。
  • $args(任意)
    登録時の設定を記述するデータです。
    • type
      この設定に関連付けられたデータのタイプ。
    • description
      この設定に付随するデータの説明。
    • sanitize_callback
      オプションの値をサニタイズするコールバック関数。
    • show_in_rest
      この設定に関連付けられたデータを REST API に含めるかどうか。
    • default
      get_option()を呼び出すときのデフォルト値

sanitize_callbackには、保存前の値を受け取り、サニタイズ後の値を返す関数を指定します。たとえば入力値を半角英数字のみに制限したい場合は、次のように実装します。

<?php
// フィールドグループを設定(sanitize_callbackでバリデーションする)
register_setting(
		"top_menu_group"
		,OPTION_KEY_NAME
		,array(
			'sanitize_callback' => 'sanitize_option_key_name',
		)
);

// 保存前に値をサニタイズする
function sanitize_option_key_name( $value ) {
	// 半角英数字以外は取り除く
	$sanitized = preg_replace( '/[^a-zA-Z0-9]/', '', (string) $value );

	if ( $sanitized === '' ) {
		add_settings_error(
			OPTION_KEY_NAME,
			'invalid_option_key_name',
			'名前は半角英数字で入力してください。'
		);
		// 空文字を返すと保存されてしまうため、変更前の値を維持する
		return get_option( OPTION_KEY_NAME );
	}

	return $sanitized;
}

sanitize_callbackを指定しない場合、入力値はそのまま保存されます。フォームからの入力を扱うときは基本的に指定しておくことをおすすめします。

セクションにフィールドを描画する

settings_fields()、do_settings_sections()、submit_button()で画面を描画します。

<?php
// トップメニュー画面を描画する
function render_menu_contents() {
	?>
	<div class = "wrap">
		<h1>テスト用オプション設定</h1>
		<form method = "post" action = "options.php" >
			<?php
				settings_fields( 'top_menu_group' );  
				do_settings_sections( BASE_SLUG ); 
				submit_button( '設定を更新' , 'primary' );
			?>
		</form>
	</div>
	<?
}

settings_fields()

settings_fields()は、設定ページのnonceやaction、option_pageフィールドを出力します。

わかっち

settings_fields()を使うことでこの画面が正当であることを証明するコードが自動されるため、管理メニューを作る際はボイラーコード的なものとして必ず利用しよう

settings_fields()の引数

  • $option_group(必須)
    設定グループ名。
    register_setting()で使用されるグループ名を一致する必要があります。

do_settings_sections()

do_settings_sections()は、特定の設定ページに追加されたすべての設定セクションを描画します。

これを設定ページのコールバック関数で使用して、add_settings_section()およびadd_settings_field()でそのページに追加されたすべてのセクションとフィールドを出力します。

do_settings_sections()の引数

  • $page(必須)
    設定セクションを出力するページのスラッグ名。

submit_button()

submit_button()は、提供されたテキストと適切なクラスを含む送信ボタンを描画します。

submit_button()はフロントエンドでは使用できず、管理画面をロードするときにのみ使用できます。

submit_button()の引数

  • $text(任意)
    ボタンのテキスト (デフォルトは「変更を保存」)
  • $type(任意)
    ボタンのタイプと CSS クラス。
    デフォルトは'primary'。
    'primary'、'small'、'large'が選択できる
  • $name(任意)
    送信ボタンの HTML のname属性。デフォルトは「submit」です。
    以下の $other_attributes に id 属性が指定されていない場合、$name がボタンの ID として使用されます。
  • $wrap(任意)
    出力ボタンを段落タグで囲む必要がある場合は true、それ以外の場合は false。デフォルトは true です。
  • $other_attributes(任意)
    tabindex を 1 に設定するなど、ボタンで出力する必要があるその他の属性。属性をその値にマッピングします。

フォーム全体の実装例

ここまでのセクション・フィールドの登録と、settings_fields() / do_settings_sections() / submit_button()による画面描画を通しでつなげると、次のようになります。

<?php
add_action( 'admin_menu', function() {
	// トップメニューを追加
	add_menu_page(
		'管理メニュータイトル',
		'テスト用トップメニュー',
		'manage_options',
		BASE_SLUG,
		'render_menu_contents',
		'dashicons-networking',
		0
	);

	// セクションを追加
	add_settings_section(
		'top_menu_section',
		'セクション',
		'render_section',
		BASE_SLUG
	);

	// フィールドを追加
	add_settings_field(
		OPTION_KEY_NAME,
		'名前',
		'render_name_field',
		BASE_SLUG,
		'top_menu_section',
		array( 'label_for' => OPTION_KEY_NAME )
	);

	// フィールドをグループに登録
	register_setting(
		'top_menu_group',
		OPTION_KEY_NAME
	);
} );

// セクションを描画する(見出しとフィールドの間に出力される)
function render_section( $args ) {
	?>
		セクションのコンテンツを記載します
		<hr>
	<?php
}

// フィールドを描画する(実際の<input>タグをechoする)
function render_name_field( $args ) {
	?>
	<input
		type="text"
		name='<?= OPTION_KEY_NAME ?>'
		value='<?= esc_attr( get_option( OPTION_KEY_NAME ) ) ?>'
	/>
	<?php
}

// トップメニュー画面を描画する
function render_menu_contents() {
	?>
	<div class="wrap">
		<h1>テスト用オプション設定</h1>
		<form method="post" action="options.php">
			<?php
				settings_fields( 'top_menu_group' );
				do_settings_sections( BASE_SLUG );
				submit_button( '設定を更新' , 'primary' );
			?>
		</form>
	</div>
	<?php
}

29〜31行目が本セクションで紹介した3つの関数です。settings_fields()でnonceなどを出力し、do_settings_sections()で登録済みのセクションとフィールドをまとめて描画、最後にsubmit_button()で送信ボタンを出力する、という一連の流れです。

まとめ

今回は、WordPressの管理メニューに設定画面を作成する方法をご紹介しました。Settings APIが登場してやや難しい印象を持たれたかもしれません。

ただ、Settings APIを使った設定画面の作成はお作法ありきの決まりきったコードのため、単純作業でよく、またデータベースへの保存・取得などは全てWordPressがうまくやってくれます。恐れずにゴリゴリソースを書いていきましょう!

次回は、WordPressの管理コンソールからデータを取得する例をご紹介したいと思います。

本記事が少しでもお役に立てれば幸いです。

最後までお読みいただき、ありがとうございました!