Создание виджета поиска с помощью WordPress REST API
Опубликовано: 2016-03-28Разработчики WordPress знают, что REST API существует уже некоторое время, но в конце прошлого года он был интегрирован в ядро, что означает, что теперь его можно использовать в виджетах и плагинах.
В этой статье мы собираемся создать простой виджет поиска с отличием. Используя WordPress REST API, этот виджет будет искать на внешнем веб-сайте WordPress и отображать результаты в виджете.
Этот пост является продолжением моего последнего поста о том, что вам нужно знать о WordPress REST API.
Создайте доступную для поиска базу знаний и помогите своим клиентам помочь самим себе.
Получить плагинСоздание плагина виджета
Как и в предыдущей статье, предполагается наличие некоторых базовых знаний о создании плагинов и виджетов. Если вы не уверены, в конце этой статьи есть рекомендации для чтения.
Давайте взглянем на существующий плагин, который мы создали в прошлой статье. Ваш код должен выглядеть примерно так:
/**
* 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' );
});
По сути, мы создали новый плагин. В этом плагине мы создали виджет, который отображает список пользовательских сообщений из базы знаний 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' );
Или, если мы хотим отображать только один случайный пост, мы можем добавить:
/posts?filter[orderby]=rand&amp;filter[posts_per_page]=1
И это то же самое для параметра поиска. В стандартном WP Query параметр будет выглядеть так:
's' => 'keyword'
Поэтому наш удаленный вызов должен выглядеть так:
$response = wp_remote_get( 'http://website-with -api.com.com/wp-json/wp/v2/posts?filter[s]=keyword');
Это довольно просто, если вы разберетесь с преобразованием параметров из WP_Query в строку URL-адреса API.
Полную информацию о доступных параметрах см. в руководстве по кодексу WP_Query.
На самом деле мы не хотим искать стандартные сообщения, мы хотим искать пользовательский тип сообщений в базе знаний. Однако, как мы видели в предыдущей статье, это легко сделать, потому что мы сделали наш пользовательский тип записи общедоступным, добавив фильтр. Поэтому все, что нам нужно сделать здесь, это запросить пользовательский тип записи базы знаний, заменив /posts/ на имя пользовательского типа записи. В данном случае /ht_kb/ . Теперь удаленный вызов будет выглядеть так:
$response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]=keyword' );
Шаг 2: Окно поиска и результаты адаптации
Итак, теперь, когда мы рассмотрели изменение запроса для фильтрации по заданному поисковому запросу, следующим шагом будет создание способа получения этого поискового запроса.
Во-первых, нам нужно добавить окно поиска в плагин. Поскольку это будет простая форма поиска, мы можем использовать функцию get_search_form(), уже настроенную WordPress, вместо создания отдельной формы поиска.
В файле плагина найдите строку с комментарием // Main Widget Content Here внутри вашей функции виджета и добавьте 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, а затем возвращает эти результаты на основе параметра поиска. Тем не мение…
Шаг 3. Изменение отображаемых результатов
Если мы протестируем новый виджет поиска, мы увидим, что виджет работает должным образом, однако он также будет возвращать результаты с текущего веб-сайта в содержимом главной страницы.

Это из-за системы шаблонов WordPress. WordPress использует строку запроса, чтобы определить, какой шаблон или набор шаблонов использовать. Поскольку, когда форма поиска отправляется, она добавляет параметр «s» к URL-адресу, он говорит WordPress выполнить поиск и перенаправить на страницу результатов поиска. В теме TwentySixteen это search.php.

Дополнительные сведения см. в документации по иерархии шаблонов.
Это здорово, если мы хотим выполнить поиск на локальном веб-сайте и на внешнем веб-сайте с использованием API одновременно, поскольку отображаются результаты для обоих. Однако в данном случае мы не хотим этого делать. Мы хотим, чтобы результаты, возвращаемые с помощью 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'. Это удаляет параметр 's' из URL-адреса.
Примечание. При таком подходе мы модифицируем основную форму поиска для поиска с использованием API вместо поиска на хост-сайте. Поэтому важно учитывать, что если мы используем основную форму поиска где-либо еще на веб-сайте, она больше не будет перенаправлять на результаты поиска с веб-сайта хоста. Чтобы иметь два разных поиска, самым простым решением было бы добавить код для этой новой формы непосредственно в виджет вместо изменения get_search_form();
Последний шаг — добавить фильтр. Это говорит WordPress заменить существующую форму этой. Мы можем вставить весь блок кода в файл плагина после класса виджета. Это можно было бы включить вместо functions.php темы, но включение его в плагин означает, что изменение формы вносится только в том случае, если плагин активирован.
Теперь, когда мы изменили имя ввода на «a», мы также должны изменить фактический параметр поиска. Параметр теперь будет отображаться в URL-адресе как: /?a=test вместо /?s=test и, следовательно, удаляет часть строки запроса, которая сообщает WordPress, что это должно перенаправлять на шаблон результатов поиска.
Чтобы вы могли искать с использованием нового параметра, обновите код, написанный ранее для удаленного вызова, чтобы использовать параметр «a» вместо «s».
Теперь это должно выглядеть так:
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 Query для поиска по-прежнему «s».
Теперь, когда мы тестируем виджет, мы должны иметь возможность искать статьи базы знаний на вашем внешнем веб-сайте и возвращать результаты без перенаправления на страницу результатов поиска.

Полный код виджета выглядит так:
/**
* 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' );
});
Это очень простая реализация пользовательского виджета поиска с использованием REST API. Как показано ранее, мы можем добавить к запросу дополнительные фильтры, чтобы ограничить количество результатов поиска или порядок их отображения. Вы можете выбрать отображение в виджете дополнительной информации, такой как условие поиска и количество результатов, или, если вы знаете jQuery/Javascript, вы можете пойти дальше и добавить хороший эффект AJAX, чтобы результаты возвращались без необходимости обновлять страницу.
Дальнейшее чтение:
- API виджетов (WordPress Codex)
- Введение в создание вашего первого виджета WordPress (Tutsplus)
- Как создать собственный виджет WordPress (WP для начинающих)
- Как создать плагин виджета для WordPress (WP Explorer)
