お問い合わせ

SWELLカスタマイズ|好きな場所にウィジェットエリアを追加する

WordPressのウィジェットは便利ですが、最新のWordrpessではウィジェットはブロックを組み合わせて作る仕組みに変わりました。

SWELLは従来のClassic Widgetが推奨になっています。

SWELLにはウィジェット領域が豊富に用意されていますが、そんなSWELLユーザーでもここにウィジェット領域があったらいいのに!と思う人は結構多いようです。

SWELLフォーラムに以下のような要望が上がっていました。

現在でも多数のウィジェットエリアをご用意いただいていますが、現在あるウィジェットエリアだと投稿ページ上部・固定ページ上部はアイキャッチの下に表示されるかと思います。

トップページ、投稿ページ、固定ページ、インデックスリスト、アーカイブページなど含めすべてのページにおいてメインカラムの最上部に表示されるウィジェットエリアが欲しいと思っており、現状はPHPファイルをいじって無理やり表示させているため、できれば標準の機能で実装していただきたいと思っております。

全てのページのメインカラム最上部に表示されるウィジェットエリアが欲しい < ご要望

投稿者は既に自分で対応しているけど、テーマ側で対応してくれたら嬉しいということで、要望を上げているようですね。

つまり、テンプレートパーツなり、テンプレートを子テーマで編集して実現しているということだと思います。

この記事では、SWELLでウィジェット領域を追加する時の手順をご紹介します。

ウィジェット領域を追加する時の基本手順

WordPressでウィジェット領域を追加する時の手順は決まっています。

  1. register_sidebar()を使ってウィジェット領域の定義を作成
  2. dynamic_sidebar()を使ってウィジェット領域の定義をテンプレートで呼び出す

SWELLがウィジェット領域を追加する時のフロー

SWELLは、Wordpressでウィジェット領域を追加する時の基本手順とやっていることは同じですが、呼び出している関数がSWELL独自関数(ラッパー)になっています。

ウィジェット領域の定義を作成

lib\widget.phpregiter_sidebar()を使ってウィジェット領域を定義しています。

widgets_initアクションフックを使っています。

/**
 * ウィジェット登録
 */
add_action( 'widgets_init', __NAMESPACE__ . '\register_area' );
function register_area() {

	// ウィジェットエリアの登録
	register_sidebar([
		'name'          => __( 'ヘッダー内部', 'swell' ),
		'id'            => 'head_box',
		'description'   => __( 'ヘッダー内に表示するウィジェット。スマホでは表示されません。', 'swell' ),
		'before_widget' => '<div id="%1$s" class="w-header__item %2$s">',
		'after_widget'  => '</div>',
		'before_title'  => '<div class="w-header__title">',
		'after_title'   => '</div>',
	]);

ウィジェット領域の定義をテンプレートで呼び出す

\SWELL_Theme::outuput_widgets( $key, $args = [] )を呼び出すと$keyをIDに持つウィジェット領域を出力することができます。

args['before']args['after']は出力のhtmlラッパーのタグです。

\SWELL_Theme::outuput_widgets( $key, $args = [] )の中身ではdynamic_sidebar()を呼び出しています。

			if ( is_front_page() ) :
				\SWELL_Theme::outuput_widgets( 'front_bottom', [
					'before' => '<div class="w-frontBottom">',
					'after'  => '</div>',
				] );
			else :
				// ウィジェット(「投稿ページ」の時)
				SWELL_Theme::outuput_content_widget( 'page', 'bottom' );
			endif;

SWELLにウィジェット領域を追加する

ウィジェットを登録する

add_action( 'widgets_init', function(){

	// ウィジェットエリアの登録
	register_sidebar([
		'name'          => __( '自前ウィジェット', 'swell' ),
		'id'            => 'jimae',
		'description'   => __( '自前のウィジェットの説明。', 'swell' ),
		'before_widget' => '<div id="%1$s" class="jimae__item %2$s">',
		'after_widget'  => '</div>',
		'before_title'  => '<div class="jimae__title">',
		'after_title'   => '</div>',
	]);
} );

ウィジェット領域を配置したいテンプレートを子テーマにコピーする

SWELLの子テーマを用意して、ウィジェットを配置したいテンプレートファイルを子テーマにコピーします。

テンプレートにウィジェット領域を配置する

コピーしたテンプレートファイルを編集し、ウィジェット出力したい箇所に、出力関数を追加します。

				\SWELL_Theme::outuput_widgets( 'jimae', [
					'before' => '<div class="w-frontBottom">',
					'after'  => '</div>',
				] );

メインカラムの最上部に表示されるウィジェットエリアを追加するには?

SWELLのメインカラムというのは、<main id="main_content"のことだと思います。

home.phpを見ると、以下のような記述となっていますので、<div class="l-mainContent__inner">の直後に作成したウィジェットエリアを配置すれば良さそうです。

<main id="main_content" class="l-mainContent l-article">
	<div class="l-mainContent__inner">
		<?php
			if ( is_front_page() ) :
				\SWELL_Theme::outuput_widgets( 'front_top', [
					'before' => '<div class="w-frontTop">',
					'after'  => '</div>',
				] );
			endif;

呼び出しているテンプレートを調べて、子テーマにコピーして、<div class="l-mainContent__inner">の直後に作成したウィジェットエリアを配置すれば目的は達成されるでしょう。

  • home.php
  • single.php
  • archive.php
  • page.php

あたりが、SWELLの標準的なサイトで使われるテンプレートになります。

修正範囲が大きくSWELLのように頻繁に親テーマが変わるテーマの場合、子テーマでやるのはちょっと躊躇しますね。

最上位のテンプレートはあまり修正が入らないとは思います

テンプレートファイルを修正せずにウィジェット領域を追加するには?

こちらの記事ではテンプレートファイルを修正せずにウィジェット領域を追加しています。

do_action()の方が汎用的じゃないか?

ウィジェットエリアを増やすのはテーマ的に対応したくないとしても、同じ場所にdo_action()を追加するのはウィジェット領域が増えるわけでもないし、他のユーザーにも見えないので、問題ないと思うんですが、どうなんでしょうか?

ユーザーはdo_action()フック内で条件判定すれば、テンプレートごとに動きを変えることもできますので、テーマの修正範囲は小さく、自由度は高いと思います。

ウィジェットをショートコード化するプラグイン(Widget Shortcode)もありますので、do_action()を仕込んでおいてくれれば、そこでウィジェットを配置できます。

shortcode内部でwidgetを呼び出し出力する仕組みもWordpressには用意されています。

the_widget()という関数を使って直接widgetをIDで呼び出すことができます。

function widget($atts) {
    
    global $wp_widget_factory;
    
    extract(shortcode_atts(array(
        'widget_name' => FALSE
    ), $atts));
    
    $widget_name = wp_specialchars($widget_name);
    
    if (!is_a($wp_widget_factory->widgets[$widget_name], 'WP_Widget')):
        $wp_class = 'WP_Widget_'.ucwords(strtolower($class));
        
        if (!is_a($wp_widget_factory->widgets[$wp_class], 'WP_Widget')):
            return '<p>'.sprintf(__("%s: Widget class not found. Make sure this widget exists and the class name is correct"),'<strong>'.$class.'</strong>').'</p>';
        else:
            $class = $wp_class;
        endif;
    endif;
    
    ob_start();
    the_widget($widget_name, $instance, array('widget_id'=>'arbitrary-instance-'.$id,
        'before_widget' => '',
        'after_widget' => '',
        'before_title' => '',
        'after_title' => ''
    ));
    $output = ob_get_contents();
    ob_end_clean();
    return $output;
    
}
add_shortcode('widget','widget'); 

関連リソース

まとめ

ウィジェット領域があったら便利だなと思う人ってフックがよくわかってない段階の人が多いと思います。

フックの仕組みがわかると、フックの中で処理すればいいので、自分がカスタマイズする場合はわざわざウィジェット領域を追加しようとは思わないと思います。

他の人にもシェアしてね
コメントを閉じる

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

クリックできる目次