Implementar búsqueda avanzada en WordPress - Soluciones para formularios de búsqueda

26 oct 2016, 05:24:21
Vistas: 1.05K
Votos: 1

Me encuentro con varios problemas al construir mi tema personalizado de WordPress:

1. Evitar codificar manualmente la URL de búsqueda en searchform.php.

Una plantilla típica podría verse así:

<form class="search" method="get" action="<?php echo get_search_link(); ?>" role="search">
    <input class="search-input" type="search" name="s">
    <button class="search-submit" type="submit" role="button">Buscar</button>
</form>

Sin embargo, nota el action="<?php echo get_search_link(); ?> la acción está codificada manualmente, asume que la ruta de búsqueda es http://homeurl/?s=xxx, ¿qué pasa si un plugin cambia la ruta de búsqueda a algo como http://homeurl/search?s=xxx?

2. Cambiar la URL de búsqueda

No me gusta la ruta predeterminada /?s=xxx para búsqueda, prefiero algo como /search?s=xxx

3. Búsqueda avanzada con más variables de consulta

Quiero buscar con palabras clave + categoría + etiqueta + valor meta, así:

Ejemplo de interfaz de búsqueda avanzada en WordPress

Tengo que establecer la URL de búsqueda para cada enlace en el panel y resaltarla cuando sea la variable de consulta actual.

¿Es esto posible?


(El problema actualizado ha sido publicado en una nueva publicación aquí)

Según la respuesta de cybmeta, hice los siguientes cambios:

add_action('pre_get_posts', 'include_any_post_type_in_search');
function include_any_post_type_in_search($query)
{
    if (!is_admin() && $query->is_search && $query->is_main_query()) {

        $tax_query = array(
            'relation' => 'AND'
        );

        if (isset($_REQUEST['c'])) {
            $cate = $_REQUEST['c'];
            array_push($tax_query, array(
                'taxonomy' => 'category',
                'terms' => sanitize_text_field($cate)
            ));
        }

        if (isset($_REQUEST['t'])) {
            $tag = $_REQUEST['t'];
            array_push($tax_query, array(
                'taxonomy' => 'post_tag',
                'terms' => sanitize_text_field($tag)
            ));
        }
        $query->set('tax_query', $tax_query);
    }
}

add_filter('query_vars', 'cyb_query_vars');
function cyb_query_vars($vars)
{
    array_push($vars, "t", "c");
    return $vars;
}

function my_get_search_url($key, $val)
{
    $query = array();

    $supported = array("c", "t", "k");
    foreach ($supported as $s) {
        if ($s == $key) {
            array_push($query, "$s=$val");
        } else {
            $old_val = get_query_var($s);
            if (isset($old_val) && !empty($old_val)) {
                array_push($query, "$s=$old_val");
            }
        }
    }
    return get_search_link(join("&", $query));
}

Luego lo uso así:

                <?php
                $cates = get_categories();
                foreach ($cates as $cate) { ?>
                    <li>
                        <a href="<?php echo my_get_search_url('c', $cate->term_id); ?>"><?php echo $cate->name; ?></a>
                    </li>
                <?php } ?>

Genera URLs como: /search/c%3D9:

1. El c=9 está codificado

2. Muestra la página de inicio en lugar de la página de resultados de búsqueda.

Y cuando visito /?c=9&s=1 obtengo resultados con la palabra clave 1 y categoría 9.

Obtengo la página de inicio para /?c=9.

Obtengo 404 para /search?c=9

Parece que hay algún problema con las reescrituras.

1
Comentarios
  1. sí, es posible. 2. Las preguntas deben ser sobre código o conceptos básicos, no tiene sentido hacer preguntas teóricas amplias ya que la respuesta suele ser corta y no muy útil
Mark Kaplun Mark Kaplun
26 oct 2016 05:41:20
Todas las respuestas a la pregunta 1
7

Si utilizas get_search_link() y alguien filtra la URL de búsqueda y la modifica, get_search_link() devolverá la URL filtrada; esa es la ventaja de las URLs no hardcodeadas. Tú o un plugin de terceros pueden modificar la URL y siempre devolverá el valor correcto. Por lo tanto, los problemas 1 y 2 parecen no existir.

El problema 3 tiene diferentes enfoques:

1.- Utilizar inputs en el formulario de búsqueda con un name igual a algún argumento de consulta aceptado directamente por WP_Query como cadena de consulta. Por ejemplo, category_name:

<form class="search" method="get" action="<?php echo get_search_link(); ?>" role="search">
    <input class="search-input" type="search" name="s">
   <select name="category_name">
        <option value="">Todas las categorías</option>
        <option value="politics">Política</option>
        <option value="economy">Economía</option>
    </select>
    <button class="search-submit" type="submit" role="button">Buscar</button>
</form>

2.- Usar cualquier cadena de consulta que desees y enganchar WP_Query en la solicitud de búsqueda con la acción pre_get_posts:

El HTML:

<form class="search" method="get" action="<?php echo get_search_link(); ?>" role="search">
    <input class="search-input" type="search" name="s">
   <select name="a_search_filter">
        <option value="">Todas las categorías</option>
        <option value="politics">Política</option>
        <option value="economy">Economía</option>
    </select>
    <button class="search-submit" type="submit" role="button">Buscar</button>
</form>

Y la acción:

add_action( 'pre_get_posts', 'cyb_advanced_search' );
function cyb_advanced_search( $query ) {

    if ( ! is_admin() && $query->is_search && $query->is_main_query() ) {

        // Establecer los parámetros de consulta que necesites
        // Por ejemplo
        $search_filter = $_REQUEST[ 'a_search_filter' ];
        $tax_query = [
            'taxonomy' => 'news',
            'field'    => 'slug',
            'terms'    =>  sanitize_text_field( $search_filter ),
        ];
        $query->set( 'tax_query', $tax_query );

    }
}

Yo añadiría la cadena de consulta al sistema de WP Rewrite:

add_filter( 'query_vars', 'cyb_query_vars' );
function cyb_query_vars( $vars ) {
  $vars[] = 'a_search_filter';
  return $vars;
}

Ahora puedes usar get_query_var() para obtener el valor de la variable de consulta personalizada:

add_action( 'pre_get_posts', 'cyb_advanced_search' );
function cyb_advanced_search( $query ) {

    if ( ! is_admin() && $query->is_search && $query->is_main_query() ) {

        // Establecer los parámetros de consulta que necesites
        // Por ejemplo
        $search_filter = get_query_var( 'a_search_filter' );
        $tax_query = [
            'taxonomy' => 'news',
            'field'    => 'slug',
            'terms'    =>  sanitize_text_field( $search_filter ),
        ];
        $query->set( 'tax_query', $tax_query );

    }
}

Finalmente, puedes obtener la solicitud actual y añadir/eliminar clases a tus enlaces y resaltarlos como desees usando CSS:

if( get_query_var(  'a_search_filter' ) ==  'category1' ) {
    $class = 'selected';
}

<a href="..." class=".<?php esc_attr_e( $class ); ?>.">Categoría 1</a>
26 oct 2016 05:53:21
Comentarios

Gracias por tu respuesta detallada. ¿Y quieres decir que todos los argumentos de consulta aceptados pueden usarse directamente en la URL de búsqueda como variables de consulta como category_name? Nunca supe eso :(

hguser hguser
26 oct 2016 06:17:38

No todos los argumentos de consulta, solo los aceptados como cadena de consulta. Por ejemplo, puedes usar https://example.com/?s=palabra_clave&category_name=politica y los resultados de búsqueda buscarán palabra_clave en publicaciones que pertenezcan a la categoría politica. Desafortunadamente, no conozco la lista exacta de argumentos que pueden usarse directamente como cadena de consulta, pero los argumentos que ves en la documentación con el formato clave=valor deberían funcionar, incluyendo post_type, author y muchos más.

cybmeta cybmeta
26 oct 2016 06:40:33

OK, lo entiendo. Lo intentaré. Por cierto, parece que hay algunas llamadas a funciones inconsistentes en tus códigos.

hguser hguser
26 oct 2016 06:49:33

Seguro, no lo probé, solo lo escribí aquí. Corregido.

cybmeta cybmeta
26 oct 2016 06:58:23

Casi lo hago funcionar, con solo un problema, he actualizado el post, ¿puedes echar un vistazo si es posible?

hguser hguser
26 oct 2016 07:12:17

Parece que tienes un problema diferente. Sería mejor si publicas una nueva pregunta e incluyes qué hace la función my_get_search_url() y qué resultado esperas. /?c=9 cargando el índice y /search?c=9 dando error 404 me parece correcto a menos que codifiques un comportamiento diferente para tales URLs; por defecto, WordPress reconoce una búsqueda (is_search() devuelve true) solo si la variable de consulta s está configurada (ver L1646 (WP 4.6) en wp-includes/query.php..

cybmeta cybmeta
26 oct 2016 10:59:06

Encuentro que creo una nueva publicación:http://wordpress.stackexchange.com/q/244088/104900

hguser hguser
27 oct 2016 00:47:14
Mostrar los 2 comentarios restantes