Implementar búsqueda avanzada en WordPress - Soluciones para formularios de búsqueda
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í:
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.

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>

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 :(

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.

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

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

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..

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