このページの本文へ

コピペで使える!WordPressのウィジェットでショートコードを使う2つの方法

2016年09月27日 09時29分更新

文●Jérémy Heleine

  • この記事をはてなブックマークに追加
本文印刷

WordPressの便利な機能、ショートコード。投稿だけでなくウィジェットでも使えたら…というときに役立つ、2つのTIpsをお届け。

WordPressのショートコードAPIについて説明した記事で検証したとおり、WordPressのショートコードを使っていろいろなことができます。ただし、WordPressのデフォルトでは、ショートコードを使用できるのは投稿(およびページ)のみで、ほかの場所では使えません。

ウィジェットでショートコードを使用したくても、デフォルトではできません。しかし、本記事ではこの機能を有効にする方法を説明します。

no shortcode in widget

テキストウィジェットでショートコードを使えるようにする

WordPressは、デフォルトで数個のウィジェットを提供しています。そのうちの1つは、その名のとおりウィジェットに任意のテキストを追加できる「テキスト」ウィジェットです。これはHTMLコードの追加にも使えます。

つまり、ウィジェットでJavaScriptコードを自由に使えるということで、とても効力を発揮するものです。ただし、サーバーに保存されたデータにアクセスするためのPHPスクリプトなどが必要な場合、ウィジェットはデフォルトのままでは役に立ちません。

これは投稿に似ています。だから投稿と同じように、ショートコードを使ってしたいことができるようにします。そのためにはwidget_textフィルターを使用します。このフィルターは「テキスト」ウィジェットの内容変更を可能にするために呼び出されます。ウィジェットでショートコードを解析するようWordPressに要求するために、ここで使用しましょう。

do_shortcode()関数のおかげでWordPressでショートコード解析ができます。これは、必須パラメーター1つとテキストの解析を受け入れ、解析したテキストを返します。つまり、widget_textフィルター内のコールバックとして、この関数を直接使用できます。

次に紹介するコードは、テーマのプラグインファイルやfunctions.phpファイルで使用できます。

<?php
add_filter('widget_text', 'do_shortcode');
?>

これで完了です。「テキスト」ウィジェットに入力したショートコードが解析されるようになりました。

shortcode

新規ショートコードウィジェットを作成する

別の方法として、独自のウィジェットの作成もできます。デフォルトの「テキスト」ウィジェットが完璧に動作するので、(/wp-includes/default-widgets.phpファイルにある)以下からコードを借用するだけです。注意したいのは、独自のプラグインを作成すべきで、コアWordPressのコアファイルは決して変更しないことです。

<?php
class WP_Widget_Text extends WP_Widget {

    public function __construct() {
        $widget_ops = array('classname' => 'widget_text', 'description' => __('Arbitrary text or HTML.'));
        $control_ops = array('width' => 400, 'height' => 350);
        parent::__construct('text', __('Text'), $widget_ops, $control_ops);
    }

    /**
     * @param array $args
     * @param array $instance
     */
    public function widget( $args, $instance ) {
        /** This filter is documented in wp-includes/default-widgets.php */
        $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );

        /**
         * Filter the content of the Text widget.
         *
         * @since 2.3.0
         *
         * @param string    $widget_text The widget content.
         * @param WP_Widget $instance    WP_Widget instance.
         */
        $text = apply_filters( 'widget_text', empty( $instance['text'] ) ? '' : $instance['text'], $instance );
        echo $args['before_widget'];
        if ( ! empty( $title ) ) {
            echo $args['before_title'] . $title . $args['after_title'];
        } ?>
            <div class="textwidget"><?php echo !empty( $instance['filter'] ) ? wpautop( $text ) : $text; ?></div>
        <?php
        echo $args['after_widget'];
    }

    /**
     * @param array $new_instance
     * @param array $old_instance
     * @return array
     */
    public function update( $new_instance, $old_instance ) {
        $instance = $old_instance;
        $instance['title'] = strip_tags($new_instance['title']);
        if ( current_user_can('unfiltered_html') )
            $instance['text'] =  $new_instance['text'];
        else
            $instance['text'] = stripslashes( wp_filter_post_kses( addslashes($new_instance['text']) ) ); // wp_filter_post_kses() expects slashed
        $instance['filter'] = ! empty( $new_instance['filter'] );
        return $instance;
    }

    /**
     * @param array $instance
     */
    public function form( $instance ) {
        $instance = wp_parse_args( (array) $instance, array( 'title' => '', 'text' => '' ) );
        $title = strip_tags($instance['title']);
        $text = esc_textarea($instance['text']);
?>
        <p><label for="<?php echo $this->get_field_id('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>

        <p><label for="<?php echo $this->get_field_id( 'text' ); ?>"><?php _e( 'Content:' ); ?></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 $text; ?></textarea></p>

        <p><input id="<?php echo $this->get_field_id('filter'); ?>" name="<?php echo $this->get_field_name('filter'); ?>" type="checkbox" <?php checked(isset($instance['filter']) ? $instance['filter'] : 0); ?> />&nbsp;<label for="<?php echo $this->get_field_id('filter'); ?>"><?php _e('Automatically add paragraphs'); ?></label></p>
<?php
    }
}
?>

ここで変更することはそれほど多くありません。最初に、クラス名を変更します。ここではWP_Widget_Shortcodesと名づけましたが、好きな名前をつけてください。また、このクラスのコンストラクタがウィジェットに関する一部の情報を設定してあるので、変更する必要があります。

<?php
public function __construct() {
    $widget_ops = array('classname' => 'widget_shortcodes', 'description' => __('Arbitrary text or HTML with shortcodes.'));
    $control_ops = array('width' => 400, 'height' => 350);
    parent::__construct('shortcodes', __('Shortcodes'), $widget_ops, $control_ops);
}
?>

ほかに変更するのは、ウィジェットの表示方法をWordPressに説明するwidget()メソッドにあります。表示するテキストが含まれている$text変数の内容を変更します。widget_textフィルターの呼び出しを削除し、コンテンツにdo_shortcode()関数を適用します。

<?php
$text = empty( $instance['text'] ) ? '' : do_shortcode($instance['text']);
?>

次に、ウィジェットを登録して、ほかのウィジェットと同じように追加できるようにします。WordPressがデフォルトのウィジェットを登録するときにトリガーされる、widgets_initアクションを使います。

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

これで、利用可能なウィジェットのリストで、ウィジェットが表示されるようになります。ウィジェットは任意のエリアに追加でき、使用するすべてのショートコードを読み取ります。

shortcodes widget

最後に

ここまで書いてきたように、ウィジェットでショートコードを使えるようにするのはそれほど複雑なことではありません。ただし、すべてのショートコードがウィジェットが表示されている場所に適応するわけではありません。ショートコードに固定幅の要素が含まれている場合、問題になることがあります。

デフォルトの「テキスト」ウィジェットに対して実施した変更点は、最小限のものです。ウィジェットをカスタマイズしたい場合は、ほかも変更できます。さらに試したい場合は、サンプルとして作成したプラグインはここからダウンロードしてください。

(原文:Quick Tip: How to Use Shortcodes Within Widgets in WordPress

[翻訳:柴田理恵/編集:Livit

Web Professionalトップへ

WebProfessional 新着記事