Crear un widget de búsqueda usando la API REST de WordPress

Publicado: 2016-03-28

Los desarrolladores de WordPress sabrán que la API REST existe desde hace algún tiempo, pero a fines del año pasado se integró en el núcleo, lo que significa que ahora se puede aprovechar en widgets y complementos.

En este artículo vamos a construir un widget de búsqueda simple con una diferencia. Con la API REST de WordPress, este widget buscará en un sitio web externo de WordPress y mostrará los resultados en el widget.

Esta publicación es la continuación de la última sobre Lo que necesita saber sobre la API REST de WordPress

Cree una base de conocimiento - ¡La manera más fácil!

Cree una base de conocimientos en la que se puedan realizar búsquedas y ayude a sus clientes a ayudarse a sí mismos.

Obtenga el complemento

Construyendo el complemento del widget

Como en el artículo anterior, se asumen algunos conocimientos básicos sobre la creación de complementos y widgets. Si no está seguro, hay algunas lecturas sugeridas para usted al final de este artículo.

Echemos un vistazo al complemento existente que creamos en el último artículo. Su código debería ser algo como esto:


/**
* 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' );
});

Esencialmente, creamos un nuevo complemento. En ese complemento, creamos un widget que muestra una lista de publicaciones personalizadas de la base de conocimientos heroicos de un sitio web diferente.

Lo que vamos a hacer ahora es modificar esto para crear también una función de búsqueda.

Paso 1: modificar la consulta básica para obtener resultados diferentes

En el último artículo, recordará que discutimos cómo OBTENER una lista de publicaciones y luego cómo cambiar los parámetros para que podamos obtener el tipo de publicación personalizada de la base de conocimientos.

Bueno, puede que no sea tan sorprendente aprender, eso no es todo lo que podemos hacer con el método GET. Al usar los parámetros de filtrado, podemos usar cualquiera de los argumentos disponibles al llamar a WP_Query. Por ejemplo, si quisiéramos cambiar la cantidad de publicaciones que se muestran, podría agregar:


/posts?filter[posts_per_page]=5

Haciendo la llamada remota algo como esto:


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

O, si quisiéramos mostrar solo una publicación aleatoria, podríamos agregar:


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

Y esto es lo mismo para un parámetro de búsqueda. En una consulta estándar de WP, el parámetro se vería así:


's' => 'keyword'

Por lo tanto, nuestra llamada remota debe verse así:


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

Es bastante simple una vez que te familiarizas con la conversión de parámetros de WP_Query en la cadena de URL de la API.

Para obtener detalles completos sobre qué parámetros están disponibles, consulte la guía del códice WP_Query.

Sin embargo, en realidad no queremos buscar publicaciones estándar, queremos buscar el tipo de publicación personalizada de la base de conocimientos. Sin embargo, como vimos en el artículo anterior, esto es fácil de hacer porque hicimos que nuestro tipo de publicación personalizada estuviera disponible públicamente al agregar un filtro. Por lo tanto, todo lo que tenemos que hacer aquí es consultar el tipo de publicación personalizada de la base de conocimiento intercambiando /publicaciones/ con el nombre del tipo de publicación personalizada. En este caso /ht_kb/ . La llamada remota ahora se verá así:


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

Paso 2: el cuadro de búsqueda y los resultados de adaptación

Entonces, ahora que analizamos la modificación de la consulta para filtrar por un término de búsqueda dado, el siguiente paso es crear una forma de obtener ese término de búsqueda.

En primer lugar, debemos agregar un cuadro de búsqueda al complemento. Debido a que solo será un formulario de búsqueda simple, podemos usar la función get_search_form() ya configurada por WordPress en lugar de crear un formulario de búsqueda separado.

En el archivo del complemento, busque la línea con el comentario // Contenido principal del widget aquí dentro de la función de su widget y agregue get_search_form(); y edite directamente debajo de él para que se vea así:


// 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>';
}

Ahora, cuando veamos el widget en la página, verá el formulario de búsqueda estándar y la lista de publicaciones de la base de conocimientos debajo.

widget de búsqueda estándar

Lo sabemos por usar get_search_form(); que cuando buscamos algo, el parámetro de búsqueda aparece en la url así:


/?s=test

's' es el parámetro $_GET y 'test' es su término de búsqueda. Por lo tanto, todo lo que queda es tomar el término de búsqueda de la URL y usarlo en la respuesta de la siguiente manera:


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/' );
}

Lo que hace este código es verificar si $_GET['s'] se ha establecido y no está vacío. Si tiene / es, entonces inclúyalo en su respuesta. De lo contrario, no se está realizando una búsqueda y desea mostrar todas las publicaciones de la base de conocimiento como de costumbre.

Puede encontrar más detalles sobre la función get_search_form() aquí.

Aquí es donde esperaríamos que terminara este artículo, ¿verdad? Después de todo, configuramos un formulario de búsqueda que consulta publicaciones en un sitio web externo utilizando la API REST de WordPress y luego devolvimos esos resultados según el parámetro de búsqueda. Sin embargo…

Paso 3: modificar los resultados mostrados

Si probamos el nuevo widget de búsqueda, podemos ver que el widget funciona como se esperaba; sin embargo, también arrojará resultados del sitio web actual en el contenido de la página principal.

resultados de la plantilla de búsqueda
Widget de búsqueda que muestra los resultados de 'prueba' y la página que redirige a la plantilla de resultados de búsqueda

Esto se debe al sistema de plantillas de WordPress. WordPress usa la cadena de consulta para determinar qué plantilla o conjunto de plantillas usar. Porque, cuando se envía el formulario de búsqueda, agrega el parámetro 's' a la URL, le está diciendo a WordPress que realice una búsqueda y redirija a la página de resultados de búsqueda. Que, en el tema de TwentySixteen es search.php.

Para obtener más información, consulte la documentación de la jerarquía de plantillas.

Eso es genial si quisiéramos realizar la búsqueda en un sitio web local y en un sitio web externo utilizando la API al mismo tiempo porque se muestran los resultados de ambos. Sin embargo, en este caso no queremos hacer eso. Solo queremos que los resultados devueltos mediante la API se muestren en el widget. La página principal no debería verse afectada.

hay muchas maneras de hacer esto. Para este ejemplo, veremos cómo modificar get_search_form(); para que ya no use 's' como su parámetro de búsqueda. En su lugar, se cambiará a 'a' para evitar el problema.

El primer paso es modificar el formulario creando una nueva función.


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 );

La función en sí es bastante simple, es básicamente un nuevo formulario para usar en lugar del formulario predeterminado. Si observamos el tema de referencia TwentySixteen e inspeccionamos el formulario de búsqueda existente, notamos que la única diferencia en el código es el nombre de la entrada de búsqueda. Originalmente era 'name=s' y ahora es 'name=a'. Esto elimina el parámetro 's' de la URL.

Nota: Con este enfoque, modificamos el formulario de búsqueda principal para buscar mediante la API en lugar de buscar en el sitio web del host. Por lo tanto, es importante tener en cuenta que si usamos el formulario de búsqueda principal en cualquier otro lugar del sitio web, ya no se redirigirá a los resultados de búsqueda del sitio web del host. Para tener dos búsquedas diferentes, la solución más fácil sería agregar el código para este nuevo formulario directamente en el widget en lugar de modificar get_search_form();

El último paso es agregar el filtro. Esto le dice a WordPress que reemplace el formulario existente con este en su lugar. Podemos pegar el bloque de código completo en el archivo del complemento después de la clase del widget. Esto podría incluirse en el functions.php del tema en su lugar, pero al incluirlo en el complemento, significa que el cambio en el formulario solo se realiza si el complemento está activado.

Ahora que hemos cambiado el nombre de la entrada a 'a', también tenemos que cambiar cuál será el parámetro de búsqueda real. El parámetro ahora aparecerá en la URL como: /?a=test, en lugar de /?s=test y, por lo tanto, eliminará la parte de la cadena de consulta que le dice a WordPress que esto debería redirigir a la plantilla de resultados de búsqueda.

Para que pueda buscar usando el nuevo parámetro, actualice el código escrito anteriormente para la llamada remota para usar el parámetro 'a' en lugar de 's'.

Ahora debería verse así:


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/' );
}

Tenga en cuenta que aunque el parámetro de búsqueda en $_GET ha cambiado, esto no cambia el filtro en la consulta real. Esto se debe a que la consulta estándar de WP para la búsqueda sigue siendo 's'.

Ahora, cuando probemos el widget, deberíamos poder buscar los artículos de la base de conocimientos en su sitio web externo y devolver los resultados sin ser redirigidos a una página de resultados de búsqueda.

Widget de búsqueda que muestra los resultados de 'prueba' sin redirigir la página
Widget de búsqueda que muestra los resultados de 'prueba' sin redirigir la página

El código completo para el widget se ve así:


/**
 * 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' );
});

Esta es una implementación muy simple de un widget de búsqueda personalizado que utiliza la API REST. Como se ilustró anteriormente, podríamos agregar filtros adicionales a la consulta para limitar la cantidad de resultados de búsqueda o el orden en que se muestran. Puede optar por mostrar información adicional en el widget, como el término de búsqueda y la cantidad de resultados, o si conoce jQuery/Javascript, puede llevar esto más lejos y agregar un buen efecto AJAX para que los resultados se devuelvan sin la necesidad de actualizar la página.

Otras lecturas:

  • API de widgets (WordPress Codex)
  • Introducción a la creación de su primer widget de WordPress (Tutsplus)
  • Cómo crear un widget de WordPress personalizado (WP Beginner)
  • Cómo crear un complemento de widget para WordPress (WP Explorer)