Búsqueda avanzada en WordPress II

busqueda_avanzada_en_wordpress_filtrando_campos

Crear consultas avanzadas con WordPress no es muy difícil y además es una buena práctica para conocer la clase WP_Query de WordPress. Esta clase nos ofrece un control muy preciso sobre las consultas a base de datos.

En un post anterior vimos cómo hacer búsquedas por categoría o taxonomía. Ahora veremos como hacer una búsqueda con varios campos de texto. Lo vemos con un ejemplo para entenderlo mejor.

Ejemplo práctico

Una web montada con WordPress necesita gestionar un catálogo de libros. Para ello dispone de un tipo de entrada llamada book, y de una taxonomía llamada author. Puedes ver cómo se hacen tipos y taxonomías personalizadas en estos posts:

La web necesita una búsqueda donde pueda filtrar por título y autor a la vez. Pero el autor no es un campo seleccionable como vimos en otra entrada sino otro campo de texto. El formulario de búsqueda tiene este aspecto:

Form Busqueda Avanzada

Y debe cumplir los siguientes criterios:

  • La búsqueda se realizará sólo en las entradas personalidadas book.
  • La consulta buscará en los campos título y contenido de los libros (Es lo que hace WordPress por defecto) y además debe cumplir que la taxonomia author asociada al libro contenga el texto introducido en el campo Autor del formulario.

Formulario de búsqueda

Necesitamos crear el formulario personalizado. Podemos copiar el formulario que viene con WordPress y añadirle dos campos nuevos

  • Un campo oculto post_type para indicarle a WordPress que busque sólo en entradas tipo book:
<input type="hidden" name="post_type" value="book" />
  • Y un campo de texto nuevo llamada search_author que necesitaremos más adelante para filtrar por autor:
<strong>Author: </strong><input type="text" class="field" name="search_author" id="search_author" size="5"

El formulario queda así:

<h2>Búsqueda Avanzada</h2>
<div>
    <form method="get" id="advanced_searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>">
        <strong>Título o Descripción: </strong><input type="text" class="field" name="s" id="s" size="5" /><br/>
        <strong>Author: </strong><input type="text" class="field" name="search_author" id="search_author" size="5" /><br/>
        <input type="hidden" name="post_type" value="book" />
        <br/>
        <input type="submit" class="submit" name="submit" id="searchsubmit" value="<?php _e( 'Go' ); ?>" />
    </form>
</div>

Registro del nuevo campo

Si queremos usar el campo search_author del formulario para nuestra consulta debemos decirselo a WordPress. Tan sólo debemos añadir este código al archivo functions.php:

function advanced_search_author_query_vars( $vars ) {
    $vars[] = 'search_author';
    return $vars;
}
add_filter( 'query_vars', 'advanced_search_author_query_vars', 1 );

Consulta personalizada

La clase WP_Query se encarga de realizar las consultas a la base de datos. Antes de realizar la consulta debemos modificar sus parámetros. Para ello utilizamos el hook pre_get_posts que nos proporcina el objeto WP_Query de la consulta y finalmente lo modificamos con nuestros criterios. Este es el código necesario y debemos añadirlo en functions.php (A continuación explicamos el código en detalle):

function advanced_search_author_filter( $query ) {

    if ( $query->is_search() ) {

        if ( isset( $query->query_vars['search_author'] ) ) {

            $tax_search_author = get_terms( 'author', array(
                'fields' => 'ids',
                'name__like' => $query->query_vars['search_author']
            ) );

            if ( !empty( $tax_search_author ) ) {

                $tax_query =  array(
                    'relation' => 'AND',
                    array(
                        'taxonomy' => 'author',
                        'field' => 'id',
                        'terms' => $tax_search_author
                    ),
                );

                $query->set( 'tax_query', $tax_query );
            }
        }
    }
    return $query;
}
add_action( 'pre_get_posts', 'advanced_search_author_filter', 1 );

Primero comprobamos si la consulta procede del formulario de búsqueda y si el parametro search_author contiene texto. De esta forma sólo realizaremos la búsqueda avanzada en las peticiones que provengan de nuestro formulario.

if ( $query->is_search() ) {

    if ( isset( $query->query_vars['search_author'] ) ) {

Buscamos en la taxonomía author los términos que contienen el texto pasado en el campo search_author. Para ello usamos la función get_terms. El parámetro name__like funciona como una consulta LIKE %loquesea% de base de datos y con el parámetro field indicamos que nos devuelva los identificadores ids.

$tax_search_author = get_terms( 'author', array(
    'fields' => 'ids',
    'name__like' => $query->query_vars['search_author']
) );

Finalmente si existe términos con el criterio anterior pasamos a modificar la consulta principal. Lo único que hay que añadir es el parametro tax_query con varios parametros. tax_query filtra las entradas y sólo muestras las que tienen los terminos de una taxonomia determinada. Éstos son los parametros que usaremos:

  • relation: AND. En este caso queremos que se cumplan todos los criterios a la vez
  • array taxonomies: Contiene el nombre de la taxonomia (en este caso author) y el array con los términos obtenidos anteriormente.
if ( !empty( $tax_search_author ) ) {

    $tax_query =  array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'author',
            'field' => 'id',
            'terms' => $tax_search_author
        ),
    );

    $query->set( 'tax_query', $tax_query );

Con este tutorial podemos ver la versatilidad de WordPress a la hora de extender funcionalidades. Esto nos puede animar a usar WordPress para muchos proyectos web.

Puedes bajar el código en este enlace. Es una plantilla hija (Child Theme) de la plantilla orbit. Contiene el código expuesto anteriormente y añade la creación de book y author como entrada y taxonomía personalizadas. El formulario está en el fichero advanced-search.php que puedes usar como plantilla en cualquier página. Si no quieres instalar la plantila orbit puedes modificar el archivo style.css y utilizar la plantilla padre que quieras.

Comentarios

  1. Hola Pedro,
    Ante todo darte las gracias por tus artículos. Los referentes a entradas personalizadas y estos sobre un buscador avanzado me están siendo de gran ayuda para desarrollar lo que quiero hacer en mi página aún sin ser una experta en programación.
    Me gustaría hacerte una consulta ya que estoy un poco bloqueada.
    Si en el formulario de búsqueda avanzada quisiera añadir más de un campo ¿cómo se añadirían a dicha búsqueda?
    ¿habría que hacer tantas funciones advanced_search_author_query_vars y advanced_search_author_filter (cambiando los nombres, obviamente) como campos de búsqueda?
    Aunque he estado consultando la documentación de codex.wordpress.org no termino de entender cómo lo tendría que hacer.
    Muchas gracias de antemano por tu respuesta y gracias nuevamente por tus contenidos 🙂

    1. Hola Eva

      Disculpa por responderte tan tarde… Puedes hacerlo como dices o sencillamente utilizar las mismas funciones y añadir los nuevos campos. Para advanced_search_author_query_vars puedes poner esto:

      $vars[] = 'search_author';
      $vars[] = 'search_otro_campo';
      return $vars;
      

      Y para la función advanced_search_author_filter puedes añadir otro condicional para el nuevo campo:

      if ( isset( $query->query_vars['search_author'] ) ) {
      ...
      }
      
      if ( isset( $query->query_vars['search_otro_campo'] ) ) {
      ...
      }
      

      Un saludo

Responder a Eva Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *