WordPress が最近注力しているカスタマイザーですが、コレをちゃんと使うといろいろ便利なことが出来ます。

たとえば、バナーを3つ管理するカスタマイザーのセクションを作ってみます。

functions.php にはこんな感じのコードを書きます。

/**
 * Customizer Setting for Banner.
 *
 * @param WP_Customize_Manager $wp_customize
 */
function my_banner_customize_register( WP_Customize_Manager $wp_customize ) {

	$wp_customize->add_panel( 'banners', array(
		'title' => 'Banners',
		'priority' => 140,
	) );

	foreach ( range( 1, 3 ) as $index ) {

		$id = 'banner_' . $index;

		/**
		 * Add setting section.
		 */
		$wp_customize->add_section( $id, array(
			'title' => sprintf( 'Banner %s', $index ),
			'panel' => 'banners',
		) );

		/**
		 * Set default value for customizer.
		 */
		$wp_customize->add_setting( $id, array(
			'default'   => get_parent_theme_file_uri( '/images/' . $id . '.jpg'  ),
			'sanitize_callback' => 'esc_url',
			'transport' => 'postMessage',
		) );

		/**
		 * For Selective refresh.
		 */
		$wp_customize->selective_refresh->add_partial( $id, array(
			'selector'            => '#'.$id,
			'render_callback'     => 'my_banner_render',
		) );

		/**
		 * Control form setting.
		 */
		$control = new WP_Customize_Image_Control( $wp_customize, $id, array(
				'label'          => 'Upload an Image',
				'section'        => $id,
			)
		);
		$wp_customize->add_control( $control );

	}
}

add_action( 'customize_register', 'my_banner_customize_register' );

/**
 * Banner markup for customizer preview.
 *
 * @param WP_Customize_Partial $partial
 * @param string $id
 */
function my_banner_render(  $partial = null, $id = '' ) {
	$image = get_theme_mod( $partial->id );
	if ( $image ): ?>
		<img src="<?php echo esc_url( $image ); ?>" alt="">
	<?php
	endif;
}

テンプレート側

<?php foreach ( range( 1, 3 ) as $index ): ?>
	<?php
	$id = 'slide_' . $index; ?>
	<div  id="<?php echo esc_attr( $id ); ?>">
		<?php my_banner_render( null, $id );?>
	</div>
<?php endforeach; ?>

基本的な設定

WP_Customize_Manager::add_section

カスタマイザーのセクションを追加します。複数の設定をまとめる場合は、後述のpanel の ID を設定する必要があります。コレを設定しない場合は、panel の設定は不要です。

WP_Customize_Manager::add_setting

テーマ設定を記述します。設定値のデフォルト値、サニタイズの関数を設定します。

ここで設定したIDでテーマオプションが保存されます。get_theme_mod でそのIDを指定すると取り出せます。'transport' => 'postMessage' を指定すると、通常プレビューがリロードされるのですが、それを止めることが出来ます。代わりに JavaScript で値を取得出来ます。(後述)

WP_Customize_Manager::add_controll

設定を変更するためのUIを定義します。WP_Customize_Control (もしくはそれを継承したクラス)のインスタンスか、連想配列を引数に持ちます。

WP_Customize_Control の引数を設定すると、テキストボックス・テキストエリア・ラジオボタン・セレクトボックス・ページ選択など様々なUIが追加できます。

WP_Customize_Control のサブクラスには色んな種類があって、色を指定するUIを追加する、WP_Customize_Color_Control や、画像を指定する、WP_Customize_Image_Control なんかがあります。

任意の設定

WP_Customize_Manager::add_panel

複数のカスタマイザーの設定をまとめるヤツです。これのIDを各セクションに指定すると、セクションをグループ化できます。

Selective Refresh を使って、部分的に更新する。

上記の設定を使えばカスタマイザーを使うことは出来ますが、変更するたびに、プレビューがリロードされて、ちょっともっさりするかもしれません。

そこで、Selective Refresh を使うと、Ajax を用いて、部分的に更新することが出来ます。

		/**
		 * For Selective refresh.
		 */
		$wp_customize->selective_refresh->add_partial( $id, array(
			'selector'            => '#'.$id,
			'render_callback'     => 'my_banner_render',
		) );

WP_Customize_Manager::selective_refresh::add_partical に対して、セレクタを指定し、その内部のコンテンツをレンダリングするコールバックを指定すると、それでその部分が Ajax で部分的に更新されます。

また、コレを使う場合、add_setting 時に、'transport' => 'postMessage' である必要があります。

要素が更新されたときに、JS を使う。

function my_banner_customize_preview_js() {
	wp_enqueue_script( 'my-banner-customizer', get_template_directory_uri() . '/js/banner-customizer.js', array(
		'customize-preview',
	), false, true );
}

add_action( 'customize_preview_init', 'my_banner_customize_preview_js' );

$(function () {

	if (wp && wp.customize && wp.customize.bind) {
		let api = wp.customize
		api.selectiveRefresh.bind('partial-content-rendered', function (partial) {

			if (partial.container) {
				// 要素が存在する場合の処理。
			}
			else {
				// 要素が存在しない場合の処理。
			}
		})
	}
})

カスタマイザーのプレビュー画面で、wp.customize というオブジェクトが渡されます。コレを使うことで、カスタマイザーの変更をJS で取得することが出来ます。 

 torounit/fesdemo にそれらを実装したサンプルがあるので、参考程度にどうぞ。また、torounit/vanilla でもカスタマイザーで機能を実装しています。

カスタムフィールドで頑張ってるケースも多いとは思うのですが、一度覚えてしまえば、カスタマイザーはかなり強力です。WordPress の標準のAPIでかなりのことができますし、Selective Refresh を使うとプレビューでのカスタマイズがスムーズになります。一度触ってみてはいかがでしょうか?