過去に「WordPressのウィジェットを作成するときの最低限の基本形について」という記事を公開しました。
これを書いた当初から3年が過ぎました。WordPressの機能が拡張されていくにつれウィジェット関連の実装も少し変わってきています。こちらの記事内容は古い点が数ヵ所ある状態でした。(そして書き方がなんか雑)
ですので、あらためてウィジェット作成に関する情報をまとめることにしました。
目次
ウィジェット作成に関する情報のまとめ
ウィジェットのクラス構成と登録
ウィジェットを構成するプログラムコードは以下になります。(まずは管理画面にウィジェットを表示するだけの最低限な内容になります)
<?php
class Widget_Template extends WP_Widget {
public function __construct() {
// 初期化処理(ウィジェットの各種設定)を行います。
parent::__construct( false, 'テンプレートウィジェット' );
}
public function widget( $args, $instance ) {
// ウィジェットの内容をWebページに出力(HTML表示)します。
}
public function form( $instance ) {
// 管理画面のウィジェット設定フォームを出力します。
}
public function update( $new_instance, $old_instance ) {
// ウィジェットオプションを安全な値で保存するためにデータ検証/無害化します。
}
}
「WP_Widget」クラスを継承し任意の名前でサブクラスを作成します。これと合わせて「widgets_init」フックでウィジェットの登録処理を行います。
<?php
function theme_register_widget() {
register_widget( 'Widget_Template' );
}
add_action( 'widgets_init', 'theme_register_widget' );
// PHP 5.3以上なら無名関数が使えるのでこれでも登録可能です
add_action( 'widgets_init', function() {
register_widget( 'Widget_Template' );
});
上記の2つのコードを記述すると、一先ず管理画面のウィジェット一覧に「テンプレートウィジェット」というウィジェットが現れます(勿論オプション設定はまだ無いです)。
以降、ウィジェットでプログラミングが必要な4つのメソッドについて説明いたします。
- コンストラクタ: __construct()
- ウィジェットをWebページに出力: widget()
- 管理画面のウィジェット設定フォームを出力: form()
- ウィジェットオプションのデータ検証/無害化: update()
1.コンストラクタ: __construct()
ウィジェットの初期化処理(各種設定)を行います。やることは大まかに分けて3項目。
- ウィジェットの情報用の設定値を配列で用意
- ウィジェットの操作用の設定値を配列で用意
- 親クラスのコンストラクタで初期化
3項目をコード化した例です。
/**
* 初期化処理(ウィジェットの各種設定)を行います。
*/
public function __construct() {
// 情報用の設定値
$widget_options = array(
'classname' => 'widget-template',
'description' => 'テンプレートウィジェットの説明文です。',
'customize_selective_refresh' => true,
);
// 操作用の設定値
$control_options = array( 'width' => 400, 'height' => 350 );
// 親クラスのコンストラクタに値を設定
parent::__construct( 'widget-template', 'テンプレートウィジェット', $widget_options, $control_options );
}
A.情報用の設定値
情報用の設定値は以下のように扱われます。
classname | 出力するウィジェットのクラス名を指定します。デフォルトはクラス名になっており、大文字はすべて小文字になります(lowercase)。「Widget_Template」なら「class=”widget_template”」となります。 |
---|---|
description | 管理画面で表示するウィジェットの説明文です。指定しなければ親クラスのコンストラクタで指定する$nameが適用されます。 |
customize_selective_refresh | カスタマイズページでリアルタイムにウィジェット要素のHTMLを更新する機能「セレクティブリフレッシュ」へ対応の有無を設定します。デフォルトはfalseです。 |
B.操作用の設定値
操作用の設定値の「width」「height」はウィジェットの設定フォームのサイズに影響が出ます。
width | ウィジェット設定ページ(外観 > ウィジェット)、カスタマイズページ(外観 > カスタマイズ)両方で扱われる値です。各々のページで挙動が違います。 ウィジェット設定ページ: 親要素に横幅が収まりきらないとき、設定フォームを開いた時の横幅に割り当てられる。 カスタマイズページ: サイドバーに横幅が収まりきらないとき、設定フォームが右側にフェードイン表示される。(UIが変わる。通常のUIはアコーディオン) |
---|---|
height | こちらはカスタマイズページ(外観 > カスタマイズ)でのみ扱われ、ウィジェット設定ページ(外観 > ウィジェット)では無視されます。カスタマイズページでwidthの値により「右側にフェードイン表示される」UIに変更された場合にのみ、設定フォームの高さが”min-height”で確保されるようになります。 |
操作用の設定値の参考画像を用意したので、こちらを見ていただければ分かりやすいでしょう。
C.親クラスのコンストラクタで初期化
親クラスのコンストラクタに各設定を渡して初期化します。
$id_base | 出力するウィジェットのidのベースとなる文字列を指定します。falseでデフォルトとなります。デフォルトはクラス名を使用しますが、クラス名によってIDの付き方が変わります。例えばクラス名が「Template_Widget」なら「id=”template_widget-{id}”」と設定されます(大文字は小文字に変換)。例外として「Widget_Template」のように接頭辞が”Widget”となっており、かつアンダースコア(_)で区切られている場合は”Widget_”が排除され「id=”template-{id}”」となります。 |
---|---|
$name | 管理画面で表示するウィジェットの名前になります。falseを指定すると空の文字列を出力します(つまりウィジェット名は表示されません) |
$widget_options | 上述した、ウィジェットの情報用の設定値を配列で渡します。(任意) |
$control_options | 上述した、ウィジェットの操作用の設定値を配列で渡します。(任意) |
コンストラクタ以外の関数、「widget()」「form()」「update()」は実装する機能によってコードが結構変わってしまうので簡単なサンプルコードを記述します。
2.ウィジェットをWebページに出力: widget()
ウィジェットの内容をWebページに出力(HTML表示)する関数です。
例としてタイトル、テキストエリアを表示するコード(WordPress標準のテキストウィジェットとほぼ同様)です。
/**
* ウィジェットの内容をWebページに出力します(HTML表示)
*
* @param array $args register_sidebar()で設定したウィジェットの開始/終了タグ、タイトルの開始/終了タグなどが渡される。
* @param array $instance 管理画面から入力した値が渡される。
*/
public function widget( $args, $instance ) {
// ウィジェットのオプション「タイトル(title)」を取得
$title = empty( $instance['title'] ) ? '' : $instance['title'];
// ウィジェットのオプション「テキスト(text)」を取得
$widget_text = ! empty( $instance['text'] ) ? $instance['text'] : '';
echo $args['before_widget']; // ウィジェット開始タグ(<div>など)
if ( ! empty( $title ) ) {
// タイトルの値をタイトル開始/終了タグで囲んで出力
echo $args['before_title'] . $title . $args['after_title'];
} ?>
<!-- 入力されたテキストを出力 -->
<div class="textwidget"><?php echo $widget_text; ?></div>
<?php
echo $args['after_widget']; // ウィジェット終了タグ(</div>など)
}
処理内容はシンプルです。設定フォーム(次で説明する関数)に入力してあるオプション「タイトル」「テキスト」を取得して、それをウィジェット用のHTMLタグで囲って出力しています。(ウィジェット用のHTMLは$args
に、オプションは$instance
に引数で渡ってきます)
引数の説明
$args | register_sidebar()で登録した値が渡ってきます。 「$args[‘before_widget’]」でウィジェット開始タグ 「$args[‘after_widget’]」でウィジェット終了タグ 「$args[‘before_title’]」でタイトル開始タグ 「$args[‘after_title’]」でタイトル終了タグ これらで登録したウィジェット用のタグが取得できるので、出力時に使います。(他にもサイドバーのIDや名前も値にあります) |
---|---|
$instance | 管理画面で入力したオプションが渡ってきます。このオプションは次の「form()」関数で用意しましょう。 |
3.管理画面のウィジェット設定フォームを出力: form()
widget()
でWebページに表示するための、オプションを入力する設定フォーム出力関数です。
引数$instance
にはWordPressに保存されているオプション値が渡ってくるので、そのまま扱います。
/**
* 管理画面のウィジェット設定フォームを出力します。
*
* @param array $instance 現在のオプション値が渡される。
*/
public function form( $instance ) {
// デフォルトのオプション値
$defaults = array(
'title' => '',
'text' => ''
);
// デフォルトのオプション値と現在のオプション値を結合
$instance = wp_parse_args( (array) $instance, $defaults );
// タイトル値の無害化(サニタイズ)
$title = sanitize_text_field( $instance['title'] );
?>
<!-- 設定フォーム: タイトル -->
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">タイトル</label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</p>
<!-- 設定フォーム: テキスト -->
<p>
<label for="<?php echo $this->get_field_id( 'text' ); ?>">内容</label>
<textarea class="widefat" rows="16" cols="20" id="<?php echo $this->get_field_id( 'text' ); ?>" name="<?php echo $this->get_field_name( 'text' ); ?>"><?php echo esc_textarea( $instance['text'] ); ?></textarea>
</p>
<?php
}
この関数での主な処理は3ステップです。
- デフォルトのオプション値を定義し(8行目)、WordPressに保存されている現在のオプション値と結合します(14行目)。値が未定義のオプション値を無くすためです。
- 必要であればオプション値の無害化を行います(17行目)。
- 設定フォームを出力します。(20行目以降)
3ステップ目の設定フォームの出力コードでは2つのメソッドを使用します。
- labelのfor属性/inputのid属性には「$this->get_field_id( ‘フィールドネーム’ )」
- inputのname属性には「$this->get_field_name( ‘フィールドネーム’ )」
この”フィールドネーム”引数にはオプションで使用している文字列を渡しましょう。今回の例だと「title」と「text」になります。
(「input」「textarea」タグに”widefat”というクラスが指定されていますが、これは要素を横幅一杯に表示するCSSプロパティが設定されています。WordPressで用意されているクラスです。また、各フォームはpタグで囲うと綺麗に整います)
4.ウィジェットオプションのデータ検証/無害化: update()
この関数もwidget()やform()同様、ウィジェット機能によってコードが変わってしまいます。が、内容はウィジェットオプションのデータ検証(バリデーション)/無害化(サニタイズ)を行うための関数です。安全な値を返してWordPressに保存してもらいます。保存処理は自動的に行ってくれます。
タイトル、テキストを無害化して返す処理です。
/**
* ウィジェットオプションのデータ検証/無害化
*
* @param array $new_instance 新しいオプション値
* @param array $old_instance 以前のオプション値
*
* @return array データ検証/無害化した値を返す
*/
public function update( $new_instance, $old_instance ) {
// 一時的に以前のオプションを別変数に退避
$instance = $old_instance;
// タイトル値を無害化(サニタイズ)
$instance['title'] = sanitize_text_field( $new_instance['title'] );
// ユーザがHTMLマークアップ権限を持っている場合(ユーザ権限の確認)
if ( current_user_can( 'unfiltered_html' ) ) {
// 全てのHTMLタグをそのまま保存
$instance['text'] = $new_instance['text'];
} else {
// 許可されたHTMLタグはそのままで、それ以外は無害化されて保存(サニタイズ)
$instance['text'] = wp_kses_post( $new_instance['text'] );
}
return $instance;
}
タイトルは余計なHTMLタグや改行を排除するsanitize_text_field()
で無害化し、テキストはHTML操作の権限が低いユーザに対してのみ無害化するwp_kses_post()
を使っています。
データ検証/無害化
ウィジェットに入力するオプション値は、型によってデータ検証/無害化の方法が変わってくるので『データ検証 – WordPress Codex 日本語版』を参考にすると良いでしょう。ユーザ権限については『ユーザーの種類と権限 – WordPress Codex 日本語版』にまとめられています。
(※WordPressでは「サニタイズ(sanitize)」という言葉が使われておりますが、実際はエスケープ処理が殆どです。誤解を招きやすい言葉で自分もよく混乱してしまうのですが関数名にならってそのまま「サニタイズ」としています)
ウィジェットのテンプレート
それでは、上述のコードをすべてまとめたウィジェットのテンプレートです。
まとめたコードではwidget()
内でタイトルに「widget_title」フィルターを追加してます。これはデフォルトで用意されてるウィジェット全てに適用されているので、テンプレートも対応する形にしました(フィルターの用途はタイトルのテキスト直前にアイコン表示などでしょうか)。
こちらをそのままfunctions.phpにコピペすると簡易なウィジェットが実装されます。以上、ご参考になれば。
ウィジェットAPIの公式ドキュメント
最後にAPIの公式ドキュメントのリンクを貼っておきます。最新のWordPressバージョン(2017年4月7日現在は4.7.3)の各デフォルトウィジェットに新たなコードが追加されていますが、まだ説明文は見当たらなかったのもあってまとめた次第です。