La búsqueda vacía devuelve todas las entradas

4 feb 2016, 14:18:01
Vistas: 22K
Votos: 9

Hoy he decidido implementar un formulario de búsqueda en mi sitio que obviamente devuelve un resultado cuando el usuario busca algo, pero me he encontrado con un pequeño problema.

Mi Problema

Cuando el usuario realiza una búsqueda sin introducir nada en el formulario de búsqueda, por alguna razón devuelve 5 Páginas, mientras que me gustaría que devolviera un mensaje que diga algo como 'El campo de búsqueda estaba vacío - Buscar de nuevo'.

¿Cómo podría hacer que esto suceda? He insertado mi código a continuación que controla mi botón de searchform y el contenido que muestra al buscar.

Código que Controla el Formulario de Búsqueda

searchform.php Este es el formulario de búsqueda donde el usuario introduce lo que quiere buscar (Tengo la sensación de que necesito agregar código aquí para verificar si está vacío)

<form role="search" method="get" id="searchform" action="<?php echo home_url('/'); ?>">
    <div>
        <label class="screen-reader-text" for="s">Buscar: </label>
        <input type="text" value="" name="s" id="s" placeholder="<?php the_search_query(); ?>" />
        <input type="submit" id="searchsubmit" value="Buscar" />
    </div>
</form>

search.php Esto muestra al usuario lo que ha buscado y obtiene la plantilla content-search para mostrar el/los nombre(s) de la(s) Página(s).

<div class="search-result">
    <div class="container">
        <div class="row">
            <div class="search">
                <?php if (have_posts()) : ?>

                    <h2>Resultados de búsqueda para: <?php the_search_query(); ?></h2>
                    <div class="light-separator small center"></div>

                    <?php
                    while (have_posts()) : the_post();

                    get_template_part('content-search', get_post_format());

                    endwhile;
                    else :
                        echo '
                        <div class="no-content"> 
                            <h3>Ups, parece que no hay resultados que coincidan con tu búsqueda.</h3>
                        </div>';
                    endif;
                ?>
                <div class="search-form"><?php get_search_form(); ?></div>
            </div>        
        </div>
    </div>
</div>

content-search.php - Esto muestra el Título de las Páginas y el Enlace Permanente de la Página

<div class="searchs">
    <h4>Páginas - <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
</div>
2
Comentarios

Parece un error. Lo investigaré y veré si puedo rastrearlo ;-)

Pieter Goosen Pieter Goosen
4 feb 2016 17:58:06

Publicando una respuesta en este momento

Pieter Goosen Pieter Goosen
4 feb 2016 18:20:00
Todas las respuestas a la pregunta 6
9
12

Solo una alternativa a la respuesta informativa de @PieterGoosen.

Después de que Pieter publicó esta parte:

if ( ! empty( $q['s'] ) ) {
    $search = $this->parse_search( $q );
}

se me ocurrió que podría ser posible volver a analizar la consulta de búsqueda, dentro del filtro posts_search, para cadenas de búsqueda vacías. Pero el método parse_search() es protegido e incluso si pudiéramos acceder a él, la búsqueda vacía solo nos daría:

AND (((wp_posts.post_title LIKE '%%') OR (wp_posts.post_content LIKE '%%'))) 

y eso simplemente buscaría todo. Así que ese camino no fue fructífero ;-)

En WordPress 4.5 cambió a:

if ( strlen( $q['s'] ) ) {
    $search = $this->parse_search( $q );
}

En su lugar, podríamos intentar detener la consulta principal, en el caso de una búsqueda vacía:

/**
 * Detiene la consulta principal en caso de una búsqueda vacía
 */
add_filter( 'posts_search', function( $search, \WP_Query $q )
{
    if( ! is_admin() && empty( $search ) && $q->is_search() && $q->is_main_query() )
        $search .=" AND 0=1 ";

    return $search;
}, 10, 2 );
4 feb 2016 20:59:47
Comentarios

@CoderSte Creo que esto debería resolver tu problema mejor que mi enfoque. No dudes en rechazar mi respuesta y aceptar esta de birgire ;-)

Pieter Goosen Pieter Goosen
4 feb 2016 21:09:41

Esa es realmente una buena idea, al detener la consulta principal los lleva a la página search.php que es lo que realmente quería en lugar de devolverlos a la página 404, aunque el método de @PieterGoosen funciona perfectamente si los usuarios quieren redirigirlos a la página 404. Gracias por la información adicional @birgire

Stephen Stephen
4 feb 2016 21:09:43

@PieterGoosen Lo he hecho, aunque tu respuesta también funciona bien, si alguien quiere redirigir una búsqueda vacía a un 404 entonces tu idea funciona perfectamente :)

Stephen Stephen
4 feb 2016 21:13:35

@CoderSte genial, disfruta y buena suerte con tu proyecto ;-)

Pieter Goosen Pieter Goosen
4 feb 2016 21:15:32

@birgire solo tengo una pregunta sobre esto - como estoy usando esto en mi código me gusta entender las cosas, y no entiendo muy bien qué es el {, 10, 2);.

Stephen Stephen
4 feb 2016 21:18:17

uf, acabo de tener que salir al clima loco que hace aquí, solo recuperando el aliento de nuevo, ;-) Esto fue principalmente sobre mi idea inicial fallida y solo pretendía ser un apéndice a la respuesta de @PieterGoosen. CoderSte: generalmente soy tan vago que tiendo a usar funciones anónimas mucho en este sitio ;-) Aquí 10 es la prioridad y 2 es el número de entradas del callback.

birgire birgire
4 feb 2016 21:25:26

Oh, gracias por aclararlo, ahora tiene sentido para mí :)

Stephen Stephen
5 feb 2016 10:41:11

La idea está aquí, pero la última solución es incorrecta. empty( $search ) debería ser reemplazado por empty( get_search_query() ) ya que $search contiene la consulta, no el slug de búsqueda. Por lo tanto, la condición if nunca es verdadera.

Gael.D Gael.D
24 abr 2019 15:37:09

@Gael.D Gracias por comentar eso, no dudes en editar y corregir la respuesta según sea necesario, gracias.

birgire birgire
24 abr 2019 21:25:02
Mostrar los 4 comentarios restantes
5

No estoy seguro si esto es un error intencional o simplemente un error que nunca se anticipó, pero definitivamente es un fallo en el diseño.

Este comportamiento existe en los siguientes casos que noté anteriormente:

  • Establecer un array vacío en post__in devuelve todas las publicaciones

  • Pasar un término inválido a un tax_query o usar el campo name con un nombre que contiene caracteres especiales o más de una palabra elimina la cláusula JOIN de la consulta SQL, lo que también resulta en que se devuelvan todas las publicaciones. Hice una respuesta sobre este problema

Lo que sucede aquí es que cuando pasamos una cadena válida a nuestra función de búsqueda, la cláusula WHERE se modifica para incluir nuestros términos de búsqueda. Normalmente así es como se ve la cláusula WHERE cuando ingresamos un término de búsqueda llamado search:

AND (((wp_posts.post_title LIKE \'%search%\') 
OR (wp_posts.post_content LIKE \'%search%\'))) 
AND wp_posts.post_type IN (\'post\', \'page\', \'attachment\', \'information\', \'event_type\', \'cameras\') 
AND (wp_posts.post_status = \'publish\' 
OR wp_posts.post_author = 1 
AND wp_posts.post_status = \'private\')

Cuando pasamos una cadena vacía, la cláusula de búsqueda se elimina del WHERE, lo que hace que se devuelvan todas las publicaciones. Así es como se ve la cláusula WHERE cuando pasamos una cadena vacía:

AND wp_posts.post_type IN (\'post\', \'page\', \'attachment\', \'information\', \'event_type\', \'cameras\') 
AND (wp_posts.post_status = \'publish\' OR wp_posts.post_author = 1 
AND wp_posts.post_status = \'private\')

Esta es la sección en WP_Query responsable de esto:

if ( ! empty( $q['s'] ) ) {
    $search = $this->parse_search( $q );
}

La forma más fácil de solucionar esto es devolver un error 404 cada vez que pasamos una cadena vacía como términos de búsqueda. Para esto necesitamos verificar si tenemos una cadena de búsqueda válida o no, y luego establecer un 404 según corresponda. Puedes probar lo siguiente:

add_action( 'pre_get_posts', function ( $q )
{
    if(    !is_admin() // Solo afecta el front-end
        && $q->is_main_query() // Solo afecta la consulta principal
        && $q->is_search() // Solo afecta la página de búsqueda
    ) {
        // Obtener los términos de búsqueda
        $search_terms = $q->get( 's' );

        // Establecer 404 si s está vacío
        if ( !$search_terms ) {
            add_action( 'wp', function () use ( $q )
            {
                $q->set_404();
                status_header(404);
                nocache_headers();
            });
        }
    }
});
4 feb 2016 18:48:04
Comentarios

Gracias por la respuesta - es realmente extraño ya que el sitio tiene como 15 páginas y solo devuelve 5, y las 5 que devuelve son realmente aleatorias. No he probado tu código todavía ya que no estoy cerca de una computadora, pero cuando llegue a una lo intentaré - básicamente quería que devolviera la página 404 como has sugerido, ya que esa es la única página con el formulario de búsqueda

Stephen Stephen
4 feb 2016 19:13:48

Bastante extraño, en mi instalación local devuelve todas las publicaciones de todos los tipos de contenido. Pero de todos modos, WP_Query es bastante complicado de manejar y a veces se comporta de manera extraña. ;-). Tómate tu tiempo y prueba esto completamente y avísame si encuentras algún error. Disfruta ;-)

Pieter Goosen Pieter Goosen
4 feb 2016 19:17:45

Lo sé, es muy extraño, el tema es que tengo como 7 páginas y algunas tienen páginas hijas, y lo raro es que no solo devuelve las páginas principales, devuelve 2 páginas principales y luego 3 páginas hijas. Probaré y te aviso, gracias por tu respuesta :)

Stephen Stephen
4 feb 2016 19:19:23

Lo increíble es que cada vez que cierro la página y la vuelvo a abrir, y luego hago una búsqueda vacía de nuevo, me devuelve páginas diferentes xD. Agregué tu código a mi functions.php y funcionó perfectamente, solo que sigue mostrando la Página 404 - ¿habría alguna manera de mostrar un título diferente en lugar de 404, como mostrar algo como "Tu búsqueda no fue encontrada"? Gracias por tu ayuda Pieter :)

Stephen Stephen
4 feb 2016 20:03:15

Lo haré después de intentarlo por mi cuenta y que Google no me dé respuestas sobre ello xD

Stephen Stephen
4 feb 2016 20:06:34
0

Si deseas excluir cadenas de búsqueda con una longitud menor a un valor definido y también la cadena de búsqueda vacía, puedes usar esta función modificada de la solución de birgire. En este ejemplo, las búsquedas vacías y las frases de búsqueda con solo una letra no darán resultados:

    add_filter( 'posts_search', function( $search, \WP_Query $q )
    {
        $sphrase = get_search_query();
        $slen = strlen($sphrase);
        $minlen = 2;
            if( ! is_admin() && $slen < $minlen && $q->is_search() && $q->is_main_query() ){
                $search .=" AND 0=1 ";
            }
        return $search;
    }, 10, 2 );
19 feb 2020 17:02:59
2

Si estás utilizando el archivo estándar search.php, es mucho más fácil simplemente agregar lógica dentro del condicional if ( have_posts())...

if ( have_posts() && $_GET['s'] != '' )

De esta manera, si el parámetro de búsqueda está vacío, no ejecuta el bucle de contenido.

11 ene 2021 19:44:38
Comentarios

Mucho más fácil de implementar que la solución con add_filter, y funciona perfectamente con un search.php personalizado también.

fbmd fbmd
12 mar 2021 11:40:59

Esto puede causar que algunos plugins funcionen incorrectamente. 1) Primero, hay muchos hooks mientras la página de búsqueda empieza a trabajar. Algunos plugins trabajan con la consulta a la base de datos y la consulta principal devuelve resultados (todos los posts) cuando el usuario realiza una búsqueda vacía. 2) Segundo, algunos plugins que trabajan con el primer proceso pueden confundirse cuando la consulta principal devuelve resultados pero la página de resultados no muestra ningún resultado, causando que los plugins funcionen incorrectamente.

vee vee
8 may 2024 11:32:13
0

Para excluir cadenas de búsqueda con una longitud menor a la definida y también la cadena de búsqueda vacía, puedes usar esta función modificada de la solución de birgire:

add_filter( 'posts_search', function( $search, \WP_Query $q )
{
    $sphrase = get_search_query();
    $slen = strlen($sphrase);
    $minlen = 2;
        if( ! is_admin() && $slen < $minlen && $q->is_search() && $q->is_main_query() ){
            $search .=" AND 0=1 ";
        }
    return $search;
}, 10, 2 );
11 jul 2020 08:22:13
0

Adicionalmente a la respuesta de Chad, también puedes hacer que evite búsquedas que solo contengan espacios, lo cual en mi caso también estaba devolviendo resultados:

if ( have_posts() && $_GET['s'] !== '' && !ctype_space($_GET['s']) )
18 ago 2022 05:10:44