https://idea-hack.com/blog/64646/
WordPressの全てのWidgetに共通の設定を追加する方法

WordPressの全てのWidgetに共通の設定を追加する方法

仕事で必要だったので、WordPressの全てのWidgetに共通の設定を追加る際に便利な即席サンプルコードをまとめました。

私が開発しているテーマ(Brandia)の開発において全てのWidgetにレスポンシブオプションを追加しました。

KAZUKI

「PCまたはモバイルだけで特定のWidgetを表示したい」というユーザー要望に応えました。

この機能はBrandia意外が提供しているWidgetにも適用できます。

やっていることは単純です。

Step 1
Widget管理ページの全てのWidgetにフォームを追加
in_widget_formフックとwidget_update_callbackフックを利用すれば、全てのWidgetに対して同じカスタムフィールドを追加できます。
Step 2
Widget出力時にカスタムフィールドの値を取得
widget_display_callbackフックを利用すれば、Widget出力時にカスタムフィールドの結果を取得して、それを元にカスタマイズを提供できます。
Brandiaの例では、ページの表示・非表示をコントロールするBootstrapのクラス名(d-blockなど)の出力をコントロールしました。

しかし、なかなか適切な情報がネットになかったので、ここでサンプルコードをまとめておきます。(WordPressのテーマ製作者にはかなり便利な情報なはずです。)

管理画面にカスタムフィールドを追加する

Brandiaではcheckboxを追加しています。まずは関数の定義です。

WordPress
<?php
function display_widgets_on_devices__premium_only( $widget, $return, $instance ) {
		$brandia_PC = isset( $instance['brandia_PC'] ) ? $instance['brandia_PC'] : true;
		$brandia_Mobile = isset( $instance['brandia_Mobile'] ) ? $instance['brandia_Mobile'] : true;
		?>
		<fieldset class="brandia-device-options">
			<legend><?php echo esc_html( __( 'Display this on', 'brandia' ) ); ?></legend>
			<label class="brandia-display-option <?php echo $brandia_PC ? 'checked' : ''; ?>" for="<?php echo $widget->get_field_id( 'brandia_PC' ); ?>">
				<input id="<?php echo $widget->get_field_id( 'brandia_PC' ); ?>" name="<?php echo $widget->get_field_name( 'brandia_PC' ); ?>" type="checkbox" value="brandia_PC" <?php echo checked( $brandia_PC ); ?> /><?php echo esc_html__( 'PC', 'brandia' ); ?>
			</label>
			<label class="brandia-display-option <?php echo $brandia_Mobile ? 'checked' : ''; ?>" for="<?php echo $widget->get_field_id( 'brandia_Mobile' ); ?>">
				<input id="<?php echo $widget->get_field_id( 'brandia_Mobile' ); ?>" name="<?php echo $widget->get_field_name( 'brandia_Mobile' ); ?>" type="checkbox" value="brandia_Mobile" <?php echo checked( $brandia_Mobile ); ?> /><?php echo esc_html__( 'Mobile', 'brandia' ); ?>
			</label>
		</fieldset>
		<?php
	}
WordPress
 <?php
function update_display_widgets_on_devices__premium_only( $instance, $new_instance ) {
		if ( isset( $new_instance['brandia_PC'] ) && $new_instance['brandia_PC'] ) {
			$instance['brandia_PC'] = true;
		} else {
			$instance['brandia_PC'] = false;
		}
		if ( isset( $new_instance['brandia_Mobile'] ) && $new_instance['brandia_Mobile'] ) {
			$instance['brandia_Mobile'] = true;
		} else {
			$instance['brandia_Mobile'] = false;
		}
		return $instance;
	}

定義したらHookを仕掛けましょう。

WordPress
<?php
add_action( 'in_widget_form', 'display_widgets_on_devices__premium_only', 10, 3 );
add_filter( 'widget_update_callback', 'update_display_widgets_on_devices__premium_only', 10, 2 );

フロント画面でカスタムフィールドを取得

Brandiaではカスタムフィールの値によって、WidgetにBootstrapのClass名を追記する作業を行いました。関数の定義をします。

WordPress
<?php
function display_widgets_on_devices__premium_only( $instance, $widget, $args ) {
		if ( ! isset( $instance['brandia_PC'] ) && ! isset( $instance['brandia_Mobile'] ) ) {
        return $instance;
    }
		if ( isset( $instance['brandia_Mobile'] ) ) {
			if ( $instance['brandia_Mobile'] ) {
				$brandia_Mobile_display_classname = 'd-block';
			} else {
				$brandia_Mobile_display_classname = 'd-none';
			}
		} else {
			$brandia_Mobile_display_classname = 'd-block';
		}

		$widget_classname = $widget->widget_options['classname'];
		if ( isset( $instance['brandia_PC'] ) ) {
			if ( $instance['brandia_PC'] ) {
				$brandia_PC_display_classname = 'd-lg-block';
			} else {
				$brandia_PC_display_classname = 'd-lg-none';
			}
		} else {
			$brandia_PC_display_classname = 'd-lg-block';
		}

		$args['before_widget'] = str_replace( $widget_classname, "{$widget_classname} {$brandia_Mobile_display_classname} {$brandia_PC_display_classname}", $args['before_widget'] );

		$widget->widget( $args, $instance );

		return false;
	}

Hookを仕掛けます。

WordPress
<?php
add_action( 'widget_display_callback', 'display_widgets_on_devices__premium_only', 10, 3 );

まとめ

実際にBrandiaに記載したコードはこれにさらにカスタマイズを加えていますが、基本的にはこんな感じでコードを書いていけば、Widgetに共通の設定項目の追加が可能です。

KAZUKI

ブログだけではなく、LMSや多言語サイト、そしてElemnetorの使用を前提としたテーマ(Brandia)を作っています。ぜひご検討ください。