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 Knowledge base의 사용자 정의 게시물 목록을 표시하는 위젯을 만들었습니다.

이제 우리가 할 일은 이것을 수정하여 검색 기능도 만드는 것입니다.

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&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에서 API url 문자열로 매개변수를 변환하는 방법에 대해 머리를 숙이고 나면 매우 간단합니다.

사용 가능한 매개변수에 대한 자세한 내용은 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() 함수를 사용할 수 있습니다.

플러그인 파일에서 // 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

''는 $_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는 쿼리 문자열을 사용하여 사용할 템플릿 또는 템플릿 집합을 결정합니다. 검색 양식을 제출할 때 URL에 매개변수 's'를 추가하여 WordPress에 검색을 수행하고 검색 결과 페이지로 리디렉션하도록 지시하기 때문입니다. TwentySixteen 테마에서 search.php가 있습니다.

자세한 내용은 템플릿 계층 문서를 참조하십시오.

로컬 웹사이트와 외부 웹사이트 모두에 대한 결과가 표시되기 때문에 API를 사용하여 동시에 검색을 수행하려는 경우 유용합니다. 그러나 이 경우에는 그렇게 하고 싶지 않습니다. API를 사용하여 반환된 결과만 위젯에 표시되기를 원합니다. 기본 페이지는 영향을 받지 않은 상태로 유지되어야 합니다.

이를 수행하는 방법에는 여러 가지가 있습니다. 이 예에서는 get_search_form()을 수정하는 방법을 살펴보겠습니다. 더 이상 's'를 검색 매개변수로 사용하지 않도록 기능을 설정합니다. 대신 문제를 우회하기 위해 ''로 변경됩니다.

첫 번째 단계는 실제로 새 함수를 만들어 양식을 수정하는 것입니다.


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' 매개변수가 제거됩니다.

참고: 이 접근 방식을 사용하면 호스트 웹 사이트를 검색하는 대신 API를 사용하여 검색하도록 기본 검색 양식을 수정합니다. 따라서 웹사이트의 다른 곳에서 기본 검색 양식을 사용하는 경우 더 이상 호스트 웹사이트 웹사이트의 검색 결과로 리디렉션되지 않는다는 점을 고려하는 것이 중요합니다. 두 가지 다른 검색을 수행하려면 가장 쉬운 솔루션은 get_search_form()을 수정하는 대신 이 새 양식에 대한 코드를 위젯에 직접 추가하는 것입니다.

마지막 단계는 필터를 추가하는 것입니다. 이것은 WordPress에 기존 양식을 대신 이 양식으로 바꾸도록 지시합니다. 위젯 클래스 뒤에 있는 플러그인 파일에 전체 코드 블록을 붙여넣을 수 있습니다. 대신 테마의 functions.php를 포함할 수 있지만, 플러그인에 포함시킨다는 것은 플러그인이 활성화된 경우에만 형식이 변경된다는 의미입니다.

이제 입력 이름을 'a'로 변경했으므로 실제 검색 매개변수도 변경해야 합니다. 이제 매개변수가 URL에 /?s=test 대신 /?a=test로 나타나므로 WordPress에 검색 결과 템플릿으로 리디렉션해야 한다고 알려주는 쿼리 문자열 부분이 제거됩니다.

새 매개변수를 사용하여 검색할 수 있도록 이전에 작성한 원격 호출 코드를 'a' 매개변수 대신 '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 쿼리가 여전히 ''이기 때문입니다.

이제 위젯을 테스트할 때 외부 웹 사이트에서 기술 자료 문서를 검색하고 검색 결과 페이지로 리디렉션되지 않고 결과를 반환할 수 있어야 합니다.

페이지 리디렉션 없이 '테스트'에 대한 결과를 표시하는 검색 위젯
페이지 리디렉션 없이 '테스트'에 대한 결과를 표시하는 검색 위젯

위젯의 전체 코드는 다음과 같습니다.


/**
 * 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 코덱스)
  • 첫 번째 WordPress 위젯 만들기 소개(Tutsplus)
  • 사용자 정의 WordPress 위젯을 만드는 방법(WP 초급)
  • WordPress용 위젯 플러그인을 만드는 방법(WP Explorer)