WordPress RESTAPIを使用した検索ウィジェットの作成

公開: 2016-03-28

WordPress開発者は、REST APIが以前から存在していることに気付くでしょうが、昨年末にコアに統合されたため、ウィジェットやプラグインで利用できるようになりました。

この記事では、違いのある単純な検索ウィジェットを作成します。 このウィジェットは、WordPress REST APIを使用して、外部のWordPress Webサイトを検索し、結果をウィジェットに表示します。

この投稿は、WordPress RESTAPIについて知っておくべきことに関する前回の投稿から続きます

ナレッジベースを作成する-簡単な方法!

検索可能なナレッジベースを構築し、顧客が自分自身を助けるのを助けます。

プラグインを入手する

ウィジェットプラグインの構築

前回の記事と同様に、プラグインとウィジェットの構築に関する基本的な知識があることを前提としています。 よくわからない場合は、この記事の最後にいくつかの推奨読書があります。

前回の記事で作成した既存のプラグインを見てみましょう。 コードは次のようになります。


/**
* Plugin Name: KB - REST API Widget
* Author: Kirsty Burgoine
*/

class REST_API_Widget extends WP_Widget {

/**
* Sets up the widgets name etc
*/
public function __construct() {
    $widget_ops = array(
        'classname' => 'rest-api-widget',
        'description' => 'A REST API widget that pulls posts from a different website'
    );
    parent::__construct( 'rest_api_widget', 'REST API Widget', $widget_ops );
}

/**
* Outputs the content of the widget
*
* @param array $args
* @param array $instance
*/
public function widget( $args, $instance ) {
    // outputs the content of the widget

    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2 /ht_kb/' );
    if( is_wp_error( $response ) ) {
        return;
    }

    $posts = json_decode( wp_remote_retrieve_body( $response ) );

    if( empty( $posts ) ) {
        return;
    }

    echo $args['before_widget'];
    if( !empty( $instance['title'] ) ) {
        echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title'];
    }

    // Main Widget Content Here
    if( !empty( $posts ) ) {
        echo '<ul>';
        foreach( $posts as $post ) {
            echo '<li><a href="' . $post->link. '">' . $post->title->rendered . '</a></li>';
        }
        echo '</ul>';
    }
    echo $args['after_widget'];
}

/**
* Outputs the options form on admin
*
* @param array $instance The widget options
*/
public function form( $instance ) {
    //outputs the options form on admin
    $title = ( !empty( $instance['title'] ) ) ? $instance['title'] : '';
    ?>
         <label for="<?php echo $this->get_field_name( 'title' ); ?>">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 ); ?>" /> 
    <?php
}
}//end class
add_action( 'widgets_init', function(){
register_widget( 'REST_API_Widget' );
});

基本的に、新しいプラグインを作成しました。 そのプラグインで、別のWebサイトのHeroicナレッジベースからのカスタム投稿のリストを表示するウィジェットを作成しました。

これから行うことは、これを修正して検索機能も作成することです。

ステップ1:さまざまな結果を得るために基本的なクエリを修正する

前回の記事では、投稿のリストを取得する方法と、代わりにナレッジベースのカスタム投稿タイプを取得できるようにパラメーターを変更する方法について説明したことを思い出してください。

まあ、学ぶことはそれほど驚くべきことではないかもしれません、それは私たちがGETメソッドでできるすべてではありません。 フィルタリングパラメータを使用することにより、WP_Queryを呼び出すときに使用可能な任意の引数を実際に使用できます。 たとえば、表示される投稿の数を変更したい場合は、次を追加できます。


/posts?filter[posts_per_page]=5

リモート呼び出しを次のようにします。


$response = wp_remote_get( 'http://website-with -api.com.com/wp-json/wp/v2/posts?filter[posts_per_page]=5' );

または、ランダムな投稿を1つだけ表示したい場合は、次を追加できます。


/posts?filter[orderby]=rand&filter[posts_per_page]=1

そして、これは検索パラメータについても同じです。 標準のWPクエリでは、パラメータは次のようになります。


's' => 'keyword'

したがって、リモート呼び出しは次のようになります。


$response = wp_remote_get( 'http://website-with -api.com.com/wp-json/wp/v2/posts?filter[s]=keyword');

パラメータをWP_QueryからAPIURL文字列に変換することに頭を悩ませれば、それは非常に簡単です。

使用可能なパラメーターの詳細については、WP_Queryコーデックスガイドを参照してください。

ただし、実際には標準の投稿を検索するのではなく、ナレッジベースのカスタム投稿タイプを検索します。 ただし、前の記事で見たように、フィルターを追加してカスタム投稿タイプを公開したため、これは簡単に実行できます。 したがって、ここで行う必要があるのは、 / posts /をカスタム投稿タイプの名前と交換することにより、ナレッジベースのカスタム投稿タイプを照会することだけです。 この場合、 / ht_kb / 。 リモート呼び出しは次のようになります。


$response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]=keyword' );

ステップ2:検索ボックスと調整結果

これで、特定の検索語でフィルタリングするようにクエリを修正することを検討しました。次のステップは、その検索語を取得する方法を作成することです。

まず、プラグインに検索ボックスを追加する必要があります。 これは単純な検索フォームにすぎないため、個別の検索フォームを作成する代わりに、WordPressによってすでに設定されているget_search_form()関数を使用できます。

プラグインファイルで、コメントのある行を探します//ウィジェット関数内のメインウィジェットコンテンツここにget_search_form();を追加します。 そのすぐ下を編集して、次のようにします。


// Main Widget Content Here
get_search_form();

if( !empty( $posts ) ) {
    echo '<ul>';
    foreach( $posts as $post ) {
        echo '<li><a href="' . $post->link. '">' . $post->title->rendered . '</a></li>';
    }
    echo '</ul>';
}

ページにウィジェットを表示すると、標準の検索フォームとその下のナレッジベースからの投稿のリストが表示されます。

標準検索ウィジェット

get_search_form();を使用することでわかります。 何かを検索すると、検索パラメータが次のようにURLに表示されます。


/?s=test

's'は$ _GETパラメータであり、 'test'は検索語です。 したがって、残っているのは、URLから検索語を取得し、次のように応答で使用することだけです。


if ( isset ( $_GET['s'] ) && !empty( $_GET['s'] ) ) {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]='.$_GET['s'] );
}
else {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb/' );
}

このコードは、$ _ GET ['s']が設定されていて、空ではないかどうかを確認します。 ある/ある場合は、応答に含めます。 そうでない場合、検索は実行されておらず、すべてのナレッジベースの投稿を通常どおりに表示する必要があります。

get_search_form()関数の詳細については、こちらをご覧ください。

これで、この記事が正しく終了すると予想されますか? 結局のところ、WordPress REST APIを使用して外部Webサイトの投稿をクエリし、検索パラメーターに基づいてそれらの結果を返す検索フォームを設定しました。 でも…

ステップ3:表示された結果を修正する

新しい検索ウィジェットをテストすると、ウィジェットが期待どおりに機能することがわかりますが、メインページのコンテンツに現在のWebサイトからの結果も返されます。

検索-テンプレート-結果
'test'の結果を表示する検索ウィジェットと検索結果テンプレートにリダイレクトするページ

これは、WordPressテンプレートシステムが原因です。 WordPressはクエリ文字列を使用して、使用するテンプレートまたはテンプレートのセットを決定します。 検索フォームが送信されると、パラメータ「s」がURLに追加されるため、WordPressに検索を実行し、検索結果ページにリダイレクトするように指示しています。 これは、TwentySixteenテーマではsearch.phpです。

詳細については、テンプレート階層のドキュメントを参照してください。

両方の結果が表示されるため、APIを使用してローカルWebサイトと外部Webサイトで同時に検索を実行したい場合に最適です。 ただし、この場合はそれを行いたくありません。 APIを使用して返された結果のみをウィジェットに表示する必要があります。 メインページは影響を受けないままにする必要があります。

これを行うにはいくつかの方法があります。 この例では、get_search_form();を修正する方法を見ていきます。 検索パラメータとして「s」を使用しないようにする関数。 代わりに、問題を回避するために「a」に変更されます。

最初のステップは、新しい関数を作成して実際にフォームを変更することです。


function api_search_form( $form ) {

 $form = '<form role="search" method="get" class="search-form" action="' . home_url( '/' ) . '">
         <label>
             <span class="screen-reader-text">' . _x( 'Search for:', 'label' ) . '</span>
             <input type="search" class="search-field" placeholder="' . esc_attr_x( 'Search …', 'placeholder' ) .'" value="' . get_search_query() . '" name="a" title="' . esc_attr_x( 'Search for:', 'label' ) .'" />
         </label>
         <button type="submit" class="search-submit"><span class="screen-reader-text">Search</span></button>
         </form>';

 return $form;
}

 add_filter( 'get_search_form', 'api_search_form', 100 );

関数自体は非常に単純で、基本的にデフォルトのフォームの代わりに使用する新しいフォームです。 参照TwentySixteenテーマを見て、既存の検索フォームを調べると、コードの唯一の違いは検索入力の名前であることがわかります。 元々は「name = s」でしたが、現在は「name = a」です。 これにより、URLから「s」パラメータが削除されます。

注:このアプローチでは、メインの検索フォームを変更して、ホストWebサイトを検索する代わりにAPIを使用して検索します。 したがって、メインの検索フォームをWebサイトの他の場所で使用すると、ホストWebサイトのWebサイトからの検索結果にリダイレクトされなくなることを考慮することが重要です。 2つの異なる検索を行うための最も簡単な解決策は、get_search_form()を修正するのではなく、この新しいフォームのコードをウィジェットに直接追加することです。

最後のステップは、フィルターを追加することです。 これは、WordPressに既存のフォームを代わりにこのフォームに置き換えるように指示します。 コードブロック全体をウィジェットクラスの後にプラグインファイルに貼り付けることができます。 これは、代わりにテーマのfunctions.phpに含めることができますが、プラグインに含めることにより、プラグインがアクティブ化されている場合にのみフォームへの変更が行われることを意味します。

入力の名前を「a」に変更したので、実際の検索パラメーターも変更する必要があります。 パラメータはURLに/?s = testではなく/?a = testとして表示されるため、WordPressに検索結果テンプレートにリダイレクトするように指示するクエリ文字列の部分が削除されます。

新しいパラメータを使用して検索できるように、リモート呼び出し用に以前に記述されたコードを更新して、「s」の代わりに「a」パラメータを使用します。

これで、次のようになります。


if ( isset ( $_GET['a'] ) && !empty( $_GET['a'] ) ) {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]='.$_GET['a'] );
} else {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb/' );
}

$ _GETの検索パラメーターは変更されていますが、実際のクエリのフィルターは変更されていないことに注意してください。 これは、検索用の標準のWPクエリがまだ「s」であるためです。

これで、ウィジェットをテストすると、外部Webサイトのナレッジベースの記事を検索して、検索結果ページにリダイレクトされることなく結果を返すことができるはずです。

ページをリダイレクトせずに「テスト」の結果を表示する検索ウィジェット
ページをリダイレクトせずに「テスト」の結果を表示する検索ウィジェット

ウィジェットの完全なコードは次のようになります。


/**
 * Plugin Name: KB - REST API Widget
 * Author: Kirsty Burgoine
*/

class REST_API_Widget extends WP_Widget {

 /**
 * Sets up the widgets name etc
 */
 public function __construct() {
     $widget_ops = array( 
     'classname' => 'rest-api-widget',
     'description' => 'A REST API widget that pulls posts from a different website');

     parent::__construct( 'rest_api_widget', 'REST API Widget', $widget_ops );
 }



 /**
 * Outputs the content of the widget
 *
 * @param array $args
 * @param array $instance
 */
 public function widget( $args, $instance ) {
     // outputs the content of the widget
     if ( isset ( $_GET['a'] ) && !empty( $_GET['a'] ) ) {
         $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]='.$_GET['a'] );
     } else {
         $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb/' );
     }

     if( is_wp_error( $response ) ) {
         return;
     }

     $posts = json_decode( wp_remote_retrieve_body( $response ) );

     if( empty( $posts ) ) {
         return;
     }

     echo $args['before_widget'];
     if( !empty( $instance['title'] ) ) {
         echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title'];
     }
 
     // Main Widget Content Here
     get_search_form();

     if( !empty( $posts ) ) { 
         echo '<ul>';
         foreach( $posts as $post ) {
             echo '<li><a href="' . $post->link. '">' . $post->title->rendered . '</a></li>';
         }
         echo '</ul>'; 
     }
     echo $args['after_widget'];
 }

 /**
 * Outputs the options form on admin
 *
 * @param array $instance The widget options
 */
 public function form( $instance ) {
     // outputs the options form on admin

     $title = ( !empty( $instance['title'] ) ) ? $instance['title'] : '';
     ?>
         <label for="<?php echo $this->get_field_name( 'title' ); ?>">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 ); ?>" />
     <?php
     }
}

function api_search_form( $form ) {

 $form = '<form role="search" method="get" class="search-form" action="' . home_url( '/' ) . '">
         <label>
             <span class="screen-reader-text">' . _x( 'Search for:', 'label' ) . '</span>
             <input type="search" class="search-field" placeholder="' . esc_attr_x( 'Search …', 'placeholder' ) .'" value="' . get_search_query() . '" name="a" title="' . esc_attr_x( 'Search                 for:', 'label' ) .'" />
         </label>
         <button type="submit" class="search-submit"><span class="screen-reader-text">Search</span></button>
         </form>';

 return $form;
}
add_filter( 'get_search_form', 'api_search_form', 100 );


add_action( 'widgets_init', function(){
 register_widget( 'REST_API_Widget' );
});

これは、RESTAPIを使用したカスタム検索ウィジェットの非常に単純な実装です。 前に示したように、クエリにフィルターを追加して、検索結果の数や表示される順序を制限できます。ウィジェットに検索語や結果の数などの追加情報を表示するか、または、 jQuery / Javascriptを知っている場合は、これをさらに進めて、ページを更新しなくても結果が返されるように、優れたAJAX効果を追加できます。

参考文献:

  • ウィジェットAPI(WordPress Codex)
  • 最初のWordPressウィジェットの作成の概要(Tutsplus)
  • カスタムWordPressウィジェットの作成方法(WP初心者)
  • WordPress用のウィジェットプラグインを作成する方法(WPエクスプローラー)