La ricerca con campo vuoto restituisce tutti i post

4 feb 2016, 14:18:01
Visualizzazioni: 22K
Voti: 9

Oggi ho deciso di implementare un modulo di ricerca sul mio sito che ovviamente restituisce un risultato quando l'utente cerca qualcosa, ma ho riscontrato un piccolo problema.

Il Mio Problema

Quando l'utente effettua una ricerca senza inserire nulla nel modulo di ricerca, per qualche motivo vengono restituite 5 Pagine mentre vorrei che venisse mostrato un messaggio del tipo 'Il campo di ricerca era vuoto - Cerca di nuovo'.

Come posso realizzare questo? Ho inserito il mio codice qui sotto che gestisce il pulsante searchform e il contenuto che viene mostrato durante la ricerca.

Codice che Controlla il Modulo di Ricerca

searchform.php Questo è il modulo di ricerca dove l'utente inserisce ciò che vuole cercare (Ho l'impressione che devo inserire del codice qui per verificare se è vuoto)

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

search.php Questo mostra all'utente cosa ha cercato e ottiene il template content-search per mostrare il nome della/e Pagina/e.

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

                    <h2>Risultati di ricerca per: <?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>Ops, sembra che nulla corrisponda alla tua ricerca.</h3>
                        </div>';
                    endif;
                ?>
                <div class="search-form"><?php get_search_form(); ?></div>
            </div>        
        </div>
    </div>
</div>

content-search.php - Questo visualizza il Titolo delle Pagine e il Permalink della Pagina

<div class="searchs">
    <h4>Pagine - <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
</div>
2
Commenti

Sembra un bug. Ci darò un'occhiata e vedrò se riesco a rintracciarlo ;-)

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

Sto pubblicando una risposta proprio ora

Pieter Goosen Pieter Goosen
4 feb 2016 18:20:00
Tutte le risposte alla domanda 6
9
12

Solo un'alternativa alla risposta informativa di @PieterGoosen.

Dopo che Pieter ha postato questa parte:

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

mi è venuto in mente che potrebbe essere possibile ri-analizzare la query di ricerca, all'interno del filtro posts_search, per stringhe di ricerca vuote. Ma il metodo parse_search() è protetto e anche se potessimo accedervi, la ricerca vuota ci darebbe semplicemente:

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

e questo cercherebbe semplicemente tutto. Quindi questa strada non era fruttuosa ;-)

In WordPress 4.5 è cambiato in:

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

In alternativa, potremmo provare a fermare la query principale, nel caso di una ricerca vuota:

/**
 * Ferma la query principale nel caso di una ricerca vuota
 */
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
Commenti

@CoderSte Penso che questo risolva il tuo problema meglio del mio approccio. Sentiti libero di rimuovere l'accettazione della mia risposta e accettare questa di birgire ;-)

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

In realtà è un'ottima idea, interrompendo la query principale li porta alla pagina search.php che è esattamente quello che volevo invece di reindirizzarli alla pagina 404, anche se il metodo di @PieterGoosen funziona perfettamente se gli utenti vogliono reindirizzarli alla pagina 404. Grazie per le informazioni aggiuntive @birgire

Stephen Stephen
4 feb 2016 21:09:43

@PieterGoosen L'ho fatto, anche se la tua risposta funziona bene, se qualcuno vuole reindirizzare una ricerca vuota a una pagina 404 allora la tua idea funziona perfettamente :)

Stephen Stephen
4 feb 2016 21:13:35

@CoderSte fantastico, divertiti e buona fortuna con il tuo progetto ;-)

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

@birgire ho solo una domanda su questo - poiché lo sto usando nel mio codice mi piace capire le cose, e non capisco bene cosa sia il {, 10, 2);.

Stephen Stephen
4 feb 2016 21:18:17

uff, sono appena dovuto uscire nel pazzo tempo che c'è qui, mi riprendo fiato ;-) Questo riguardava soprattutto la mia idea iniziale fallita ed era solo un'appendice alla risposta di @PieterGoosen. CoderSte: in genere sono così pigro che tendo a usare molte funzioni anonime su questo sito ;-) Qui 10 è la priorità e 2 è il numero di input della callback.

birgire birgire
4 feb 2016 21:25:26

Oh grazie per aver chiarito, ora ha senso per me :)

Stephen Stephen
5 feb 2016 10:41:11

L'idea è qui, ma l'ultima soluzione è sbagliata. empty( $search ) dovrebbe essere sostituito da empty( get_search_query() ) poiché $search contiene la query, non lo slug della ricerca. Quindi, la condizione if non è mai vera.

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

@Gael.D Grazie per il commento, sentiti libero di modificare e correggere la risposta come necessario, grazie.

birgire birgire
24 apr 2019 21:25:02
Mostra i restanti 4 commenti
5

Non sono sicuro se si tratti di un bug intenzionale o semplicemente di un bug mai anticipato, ma è sicuramente un difetto di progettazione.

Questo comportamento esiste nei seguenti casi che ho annotato in precedenza

  • Impostare un array vuoto su post__in restituisce tutti i post

  • Passare un termine non valido a una tax_query o utilizzare il campo name con un nome contenente caratteri speciali o più di una parola rimuove la clausola di join dalla query SQL, il che comporta anche il ritorno di tutti i post. Ho fatto una risposta riguardo a questo problema

Quindi quello che succede qui è che quando passiamo una stringa valida alla nostra funzione di ricerca, la clausola WHERE viene modificata per includere i nostri termini di ricerca. Normalmente ecco come appare la clausola WHERE quando inseriamo un termine di ricerca chiamato 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\')

Quando passiamo una stringa vuota, la clausola di ricerca viene rimossa dalla clausola WHERE, il che fa sì che vengano restituiti tutti i post. Ecco come appare la clausola WHERE quando passiamo una stringa vuota

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\')

Questa è la sezione in WP_Query responsabile di questo comportamento

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

Il modo più semplice per uscire da questa situazione è restituire un 404 ogni volta che passiamo una stringa vuota come termine di ricerca. Per fare ciò, dobbiamo verificare se abbiamo una stringa di ricerca valida o meno, e quindi impostare un 404 di conseguenza. Puoi provare il seguente codice

add_action( 'pre_get_posts', function ( $q )
{
    if(    !is_admin() // Solo nel front end
        && $q->is_main_query() // Solo la query principale
        && $q->is_search() // Solo la pagina di ricerca
    ) {
        // Ottieni i termini di ricerca
        $search_terms = $q->get( 's' );

        // Imposta un 404 se s è vuoto
        if ( !$search_terms ) {
            add_action( 'wp', function () use ( $q )
            {
                $q->set_404();
                status_header(404);
                nocache_headers();
            });
        }
    }
});
4 feb 2016 18:48:04
Commenti

Grazie per la risposta - è davvero strano perché il sito ha circa 15 pagine e ne restituisce solo 5, e le 5 che restituisce sono davvero casuali. Non ho ancora testato il tuo codice perché non sono vicino a un computer, ma quando ci sarò proverò - fondamentalmente volevo che restituisse la pagina 404 come hai suggerito, dato che è l'unica pagina con il modulo di ricerca

Stephen Stephen
4 feb 2016 19:13:48

Molto strano, sulla mia installazione locale restituisce tutti i post di tutti i tipi di contenuto. Comunque, WP_Query è piuttosto complicato da gestire e a volte si comporta in modo strano. ;-). Prenditi il tuo tempo e testalo completamente, fammi sapere se trovi qualche bug. Buon divertimento ;-)

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

Lo so, è molto strano, il fatto è che ho circa 7 pagine e alcune hanno pagine figlie, e la cosa strana è che non restituisce solo le pagine genitore, ma 2 pagine genitore e poi 3 pagine figlie. Proverò e ti farò sapere, grazie per la risposta :)

Stephen Stephen
4 feb 2016 19:19:23

La cosa incredibile è che ogni volta che chiudo la pagina e la riapro e poi svuoto di nuovo la ricerca, restituisce pagine diverse xD Ho aggiunto il tuo codice al mio functions.php e ha funzionato perfettamente, ma continua a mostrare la pagina 404 - ci sarebbe un modo per visualizzare un titolo diverso invece di 404, tipo "La tua ricerca non è stata trovata"? Grazie per il tuo aiuto Pieter :)

Stephen Stephen
4 feb 2016 20:03:15

Lo farò dopo aver provato a farlo da solo e Google non mi dà risposte su come fare xD

Stephen Stephen
4 feb 2016 20:06:34
0

Se vuoi escludere le stringhe di ricerca con una lunghezza inferiore a un valore definito e anche la stringa di ricerca vuota, puoi utilizzare questa funzione modificata della soluzione di birgire. In questo esempio, le frasi di ricerca vuote e quelle con una sola lettera non restituiranno risultati:

    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

Se stai utilizzando il file search.php standard, è molto più semplice aggiungere la logica all'interno del condizionale if ( have_posts())...

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

In questo modo, se il parametro di ricerca è vuoto, non esegue il loop del contenuto.

11 gen 2021 19:44:38
Commenti

Molto più facile da implementare rispetto alla soluzione con add_filter, e funziona perfettamente anche con un search.php personalizzato.

fbmd fbmd
12 mar 2021 11:40:59

Questo potrebbe causare il funzionamento errato di alcuni plugin. 1) Innanzitutto, ci sono molti hook quando la pagina di ricerca inizia a funzionare. Alcuni plugin lavorano con la query del database e la query principale restituisce risultati (tutti i post) quando l'utente inserisce una ricerca vuota. 2) In secondo luogo, alcuni plugin che lavorano con il primo processo potrebbero confondersi quando la query principale restituisce risultati ma la pagina dei risultati di ricerca non mostra alcun risultato, causando un funzionamento errato dei plugin.

vee vee
8 mag 2024 11:32:13
0

Per escludere le stringhe di ricerca con una lunghezza inferiore a un valore definito e anche la stringa di ricerca vuota, puoi utilizzare questa funzione modificata della soluzione di 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 lug 2020 08:22:13
0

Aggiungendo alla risposta di Chad, puoi anche impedire ricerche con solo spazi, che nel mio caso restituivano comunque risultati:

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