ウィジェット

2020.04.05 2020.04.05

TOPICS

翻訳元記事はこちらです。

ウィジェットは、ウィジェットエリア(サイドバーとも呼ばれる)にコンテンツや機能を追加します。ウィジェットエリアは、ユーザーがサイトをカスタマイズするための方法を提供します。ウィジェットエリアは、複数のページに表示することもできますし、1つのページにのみ表示することもできます。あなたのテーマには、1つのウィジェットエリアしかない場合もあれば、多数のウィジェットエリアがある場合もあります。

ウィジェットエリアを使用する方法の例としては、以下のようなものがあります。

ウィジェットは、いくつかのHTMLを出力するPHPオブジェクトです。同じ種類のウィジェットを同じページで複数回使用することができます。 (例: テキストウィジェット)
ウィジェットは、データベースにデータを保存することができます。 (オプションテーブルにあります)

新しい種類のウィジェットを作成すると、ユーザーの管理画面の「外観」→「ウィジェット」に表示されます。ユーザーは、WordPressの管理画面からウィジェットエリアへの追加やウィジェットの設定のカスタマイズを行うことができます。

組み込みウィジェットとスタンドアロンウィジェットの比較

WordPress のデフォルトのインストールには、ウィジェットのセットが含まれています。これらの標準的なウィジェットに加えて、テーマやプラグインによって追加のウィジェットを含めることができます。テーマやプラグインに組み込まれたウィジェットの利点は、追加機能を提供し、ウィジェットの数を増やすことです。

欠点は、テーマが変更されたり、プラグインが非アクティブ化されると、プラグインやテーマウィジェットの機能が失われてしまうことです。しかし、ウィジェットのデータと設定はオプションテーブルに保存され、テーマやプラグインが再起動された場合に復元されます。

テーマにウィジェットを含める場合、そのテーマがアクティブな場合にのみ使用できます。ユーザーがテーマを変更すると、そのウィジェットにアクセスできなくなります。しかし、ウィジェットがプラグインに含まれている場合、ユーザーはウィジェット機能へのアクセスを失うことなくテーマを変更することができます。

ウィジェットの解説

視覚的には、ウィジェットは2つの領域で構成されています。

  1. タイトルエリア
  2. ウィジェットオプション

ウィジェットによって出力されるHTMLのサンプルです。

<div id="text-7" class="widget widget_text">
<!-- Widget Container -->
    <div class="widget-wrap">
        <h4 class="widgettitle">This is a text widget</h4>
        <!-- Title -->
        <div class="textwidget">
        <!-- Content of Widget -->
            I can put HTML in here. <a href="http://google.com/">Search me!</a>
        </div>
    </div>
</div>

各ウィジェットは、表示されているデータに関連するHTMLを出力する独自の方法を持っています。ウィジェットのラッパータグは、表示されているウィジェットの領域によって定義されます。

組み込みのテキストウィジェットのようなウィジェットを作成するために必要なPHPコードは次のようになります。

<?php
 
class My_Widget extends WP_Widget {
 
    function __construct() {
 
        parent::__construct(
            'my-text',  // Base ID
            'My Text'   // Name
        );
 
        add_action( 'widgets_init', function() {
            register_widget( 'My_Widget' );
        });
 
    }
 
    public $args = array(
        'before_title'  => '<h4 class="widgettitle">',
        'after_title'   => '</h4>',
        'before_widget' => '<div class="widget-wrap">',
        'after_widget'  => '</div></div>'
    );
 
    public function widget( $args, $instance ) {
 
        echo $args['before_widget'];
 
        if ( ! empty( $instance['title'] ) ) {
            echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
        }
 
        echo '<div class="textwidget">';
 
        echo esc_html__( $instance['text'], 'text_domain' );
 
        echo '</div>';
 
        echo $args['after_widget'];
 
    }
 
    public function form( $instance ) {
 
        $title = ! empty( $instance['title'] ) ? $instance['title'] : esc_html__( '', 'text_domain' );
        $text = ! empty( $instance['text'] ) ? $instance['text'] : esc_html__( '', 'text_domain' );
        ?>
        <p>
        <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php echo esc_html__( 'Title:', 'text_domain' ); ?></label>
            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
        </p>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'Text' ) ); ?>"><?php echo esc_html__( 'Text:', 'text_domain' ); ?></label>
            <textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>" type="text" cols="30" rows="10"><?php echo esc_attr( $text ); ?></textarea>
        </p>
        <?php
 
    }
 
    public function update( $new_instance, $old_instance ) {
 
        $instance = array();
 
        $instance['title'] = ( !empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
        $instance['text'] = ( !empty( $new_instance['text'] ) ) ? $new_instance['text'] : '';
 
        return $instance;
    }
 
}
$my_widget = new My_Widget();
?>

上記のコードについては、後ほど記事で詳しく説明します。

ウィジェットの開発

ウィジェットを開発するには、以下の手順が必要です。

  1. 標準の WP_Widget クラスとその関数の一部を拡張して、ウィジェットのクラスを作成します。
  2. ウィジェット画面で利用できるように登録します。
  3. あなたのテーマには、ウィジェットを追加するためのウィジェットエリアが少なくとも1つあることを確認してください。

Widget Classのサンプル

WP_Widgetクラスは、wp-includes/class-wp-widget.php にあります。

<?php
 
class My_Widget extends WP_Widget {
 
    public function __construct() {
        // actual widget processes
    }
 
    public function widget( $args, $instance ) {
        // outputs the content of the widget
    }
 
    public function form( $instance ) {
        // outputs the options form in the admin
    }
 
    public function update( $new_instance, $old_instance ) {
        // processes widget options to be saved
    }
}
 
?>

これらの各関数のドキュメントは、ウィジェットクラスのコードにあります。

  1. construct:管理画面でウィジェットの説明、名前、表示幅を設定します。
  2. widget:ウィジェットのオプションを処理し、ページにHTMLを表示します。$argsパラメータは、ウィジェットのタイトルクラスとウィジェットのコンテンツクラスを表示するために使用できるHTMLを提供します。
  3. form:ウィジェットのオプションを設定するために使われるフォームを表示します。ウィジェットにオプションがない場合、この関数をスキップすることができます。 (ただし、空であっても含めるのがベストプラクティスです)
  4. update:ウィジェットのオプションをデータベースに保存します。ウィジェットにオプションがない場合、この関数をスキップすることができます。(ただし、空であっても含めることが最善の方法です)

ウィジェットの登録

register_widget()関数を使って、ウィジェットを登録します。

この関数は、widgets_initフックで呼び出します。

<?php
add_action( 'widgets_init', 'wpdocs_register_widgets' );
 
function wpdocs_register_widgets() {
    register_widget( 'My_Widget' );
}
?>

ウィジェットをラップするHTMLや、タイトルやウィジェットの内容を表すクラスは、 register_sidebar()を使ってウィジェット領域を登録する際に指定します。

テキストウィジェットの例

冒頭の例のテキストウィジェットを構築するには まずはWP_Widgetクラスを継承したウィジェットクラスを設定します。

クラスのコンストラクタで親コンストラクタを呼び出し、ウィジェットのベースIDと名前を渡します。また、クラスのコンストラクタでウィジェットを登録するためにwidget_initアクションにフックします。

次に、ウィジェットを作成する際に使用する引数を宣言します。定義しなければならない引数は、before_titleafter_titlebefore_widgetafter_widgetの4つです。これらの引数はウィジェットのタイトルとウィジェット自体をラップするコードを定義します。

引数を定義した後、widget関数を定義します。この関数は2つのパラメータ、先ほどの$args配列とウィジェットの$instanceを受け取り、フォームからのオプションを処理し、サイトのフロントエンドにウィジェットのHTMLを表示する関数です。
上の例では、ウィジェット関数は単純にウィジェットのタイトルを出力し、それをwidget_titleフィルターに通しています。そして、シンプルなウィジェットのラッパーとウィジェットのテキストフィールドの内容を出力します。
例で説明したように、$instanceに格納されたウィジェットからオプションにアクセスすることができます。

次にform関数を定義します。この関数は$instanceという1つのパラメータを受け取り、ユーザーがウィジェットの管理画面でウィジェットを作成する際に使用するフォームを出力します。上の例では、この関数は$title$text変数を定義し、それらの値が存在する場合は前に入力された値に設定することから始まります。次に、タイトル用のテキストフィールドとテキスト内容用のテキストエリアを持つシンプルなフォームを出力します。

最後にupdate関数を定義します。この関数は $new_instance$old_instance の2つのパラメータをとり、ウィジェットが投稿されたときに新しいオプションで更新します。ここでは、$instanceを空の配列として定義します。次に、タイトルとテキストキーを $new_instance の値に設定します。そして $instance を返します。

最後に、上記のすべてが定義されたら、新しいウィジェットクラスのインスタンスを作成し、コードをテストします。

サンプルウィジェット

<?php
 
/**
 * Adds Foo_Widget widget.
 */
class Foo_Widget extends WP_Widget {
 
    /**
     * Register widget with WordPress.
     */
    public function __construct() {
        parent::__construct(
            'foo_widget', // Base ID
            'Foo_Widget', // Name
            array( 'description' => __( 'A Foo Widget', 'text_domain' ), ) // Args
        );
    }
 
    /**
     * Front-end display of widget.
     *
     * @see WP_Widget::widget()
     *
     * @param array $args     Widget arguments.
     * @param array $instance Saved values from database.
     */
    public function widget( $args, $instance ) {
        extract( $args );
        $title = apply_filters( 'widget_title', $instance['title'] );
 
        echo $before_widget;
        if ( ! empty( $title ) ) {
            echo $before_title . $title . $after_title;
        }
        echo __( 'Hello, World!', 'text_domain' );
        echo $after_widget;
    }
 
    /**
     * Back-end widget form.
     *
     * @see WP_Widget::form()
     *
     * @param array $instance Previously saved values from database.
     */
    public function form( $instance ) {
        if ( isset( $instance[ 'title' ] ) ) {
            $title = $instance[ 'title' ];
        }
        else {
            $title = __( 'New title', 'text_domain' );
        }
        ?>
        <p>
            <label for="<?php echo $this->get_field_name( 'title' ); ?>"><?php _e( '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>
    <?php
    }
 
    /**
     * Sanitize widget form values as they are saved.
     *
     * @see WP_Widget::update()
     *
     * @param array $new_instance Values just sent to be saved.
     * @param array $old_instance Previously saved values from database.
     *
     * @return array Updated safe values to be saved.
     */
    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( !empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
 
        return $instance;
    }
 
} // class Foo_Widget
 
?>

サンプルウィジェットはwidgets_initフックで以下のように登録します。

<?php
// Register Foo_Widget widget
add_action( 'widgets_init', 'register_foo' );
     
function register_foo() { 
    register_widget( 'Foo_Widget' ); 
}
?>

特別な配慮

サイドバーではなく、別のテンプレートファイル内でウィジェットを使用したい場合は、the_widget()を使用してプログラムで表示することができます。この関数は、引数で、ウィジェットのクラス名を受け付けます。このようにウィジェットクラス名を関数に渡します。

<?php the_title(); ?>
 
<div class="content">
    <?php the_content(); ?>
</div>
 
<div class="widget-section">
    <?php the_widget( 'My_Widget_Class' ); ?>
</div>

例えば、サイトのフロントページのセクションでフォームの横にイベントのリストを表示したり、ナビゲーションと一緒にメガメニューにメールキャプチャフォームを表示するなど、ページの特定の領域でウィジェットを使用する必要がある場合に、このアプローチを使用することができます。