Căutarea goală returnează toate postările

4 feb. 2016, 14:18:01
Vizualizări: 22K
Voturi: 9

Astăzi am decis să implementez un formular de căutare pe site-ul meu care să returneze evident un rezultat atunci când utilizatorul caută ceva, dar m-am lovit de o mică problemă.

Problema mea

Când utilizatorul face o căutare fără a introduce nimic în formularul de căutare, din anumite motive returnează 5 Pagini, în timp ce aș dori să returneze un Mesaj care să spună ceva de genul 'Câmpul de căutare a fost gol - Căutați din nou'.

Cum aș putea realiza acest lucru? Am inserat mai jos codul meu care controlează butonul searchform și conținutul pe care îl afișează la căutare.

Codul care controlează Formularul de Căutare

searchform.php Acesta este formularul de Căutare unde utilizatorul introduce ce dorește (Am sentimentul că trebuie să introduc niște cod aici pentru a verifica dacă este gol)

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

search.php Acesta arată utilizatorului ce a căutat și obține șablonul content-search pentru a afișa numele Paginii/Paginilor.

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

                    <h2>Rezultatul căutării pentru: <?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, se pare că nimic nu se potrivește cu căutarea ta.</h3>
                        </div>';
                    endif;
                ?>
                <div class="search-form"><?php get_search_form(); ?></div>
            </div>        
        </div>
    </div>
</div>

content-search.php - Acesta afișează Titlul Paginilor și Permalink-ul pentru Pagină

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

Pare să fie o eroare. O să investighez și voi încerca să o depanez ;-)

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

Postez un răspuns chiar acum

Pieter Goosen Pieter Goosen
4 feb. 2016 18:20:00
Toate răspunsurile la întrebare 6
9
12

Doar o alternativă la răspunsul informativ oferit de @PieterGoosen.

După ce Pieter a postat această parte:

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

mi-a trecut prin minte că ar putea fi posibil să reanalizăm interogarea de căutare, în cadrul filtrului posts_search, pentru un șir de căutare gol. Dar metoda parse_search() este protejată și chiar dacă am putea accesa-o, căutarea goală ne-ar oferi doar:

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

și asta ar căuta pur și simplu totul. Așa că această cale nu a fost productivă ;-)

În WordPress 4.5 s-a schimbat în:

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

În schimb, am putea încerca să oprim interogarea principală, în cazul unei căutări goale:

/**
 * Oprește interogarea principală în cazul unei căutări goale
 */
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
Comentarii

@CoderSte Cred că aceasta ar rezolva problema ta mai bine decât abordarea mea. Te rog să nu eziti să retragi acceptarea răspunsului meu și să accepți acesta de la birgire ;-)

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

Aceasta este de fapt o idee bună, prin oprirea interogării principale, utilizatorii sunt redirecționați către pagina search.php, care era exact ceea ce doream, în loc să fie returnați pe pagina 404. Deși metoda lui @PieterGoosen funcționează perfect dacă utilizatorii doresc să fie redirecționați către pagina 404, Mulțumesc pentru informația suplimentară @birgire

Stephen Stephen
4 feb. 2016 21:09:43

@PieterGoosen Am făcut asta, deși răspunsul tău funcționează și el bine, dacă cineva dorește să redirecționeze o căutare goală către o pagină 404, atunci ideea ta funcționează perfect :)

Stephen Stephen
4 feb. 2016 21:13:35

@CoderSte super, distrează-te și mult succes cu proiectul tău ;-)

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

@birgire am doar o întrebare despre asta - pentru că folosesc acest lucru în codul meu și vreau să înțeleg lucrurile, și nu prea înțeleg ce este {, 10, 2);.

Stephen Stephen
4 feb. 2016 21:18:17

uf, tocmai a trebuit să ies afară în vremea nebună de acum, abia îmi revin ;-) Asta a fost în mare parte despre ideea mea inițială eșuată și era menită să fie doar un anex la răspunsul lui @PieterGoosen. CoderSte: sunt în general atât de leneș încât tind să folosesc multe funcții anonime pe acest site ;-) Aici 10 este prioritatea și 2 este numărul de intrări ale callback-ului.

birgire birgire
4 feb. 2016 21:25:26

Oh, mulțumesc pentru clarificare, acum înțeleg :)

Stephen Stephen
5 feb. 2016 10:41:11

Ideea este bună, dar ultima soluție este greșită. empty( $search ) ar trebui înlocuit cu empty( get_search_query() ) deoarece $search conține interogarea, nu slug-ul căutării. Așadar, condiția if nu este niciodată adevărată.

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

@Gael.D Mulțumesc pentru comentariu, te rog să te simți liber să editezi și să corectezi răspunsul după cum consideri necesar, mulțumesc.

birgire birgire
24 apr. 2019 21:25:02
Arată celelalte 4 comentarii
5

Nu sunt sigur dacă acesta este un bug intenționat sau doar un bug care nu a fost anticipat niciodată, dar este cu siguranță o deficiență în design.

Acest comportament există în următoarele cazuri pe care le-am notat anterior

  • Setarea unui array gol la post__in returnează toate articolele

  • Transmiterea unui termen invalid către un tax_query sau utilizarea câmpului name cu un nume care conține caractere speciale sau mai multe cuvinte elimină clauza JOIN din interogarea SQL, ceea ce duce, de asemenea, la returnarea tuturor articolelor. Am făcut un răspuns referitor la această problemă

Deci, ceea ce se întâmplă aici este că atunci când transmitem un șir valid către funcția noastră de căutare, clauza WHERE este modificată pentru a include termenii noștri de căutare. În mod normal, așa arată clauza WHERE când introducem un termen de căutare numit 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\')

Când transmitem un șir gol, clauza de căutare este eliminată din clauza WHERE, ceea ce duce la returnarea tuturor articolelor. Așa arată clauza WHERE când transmitem un șir gol

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

Aceasta este secțiunea din WP_Query care este responsabilă pentru aceasta

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

Cea mai ușoară modalitate de a ieși din această situație este să returnăm un 404 ori de câte ori transmitem un șir gol ca termeni de căutare. Pentru aceasta, trebuie să verificăm dacă avem un șir de căutare valid sau nu și apoi să setăm un 404 în funcție de aceasta. Puteți încerca următoarele

add_action( 'pre_get_posts', function ( $q )
{
    if(    !is_admin() // Doar în front-end
        && $q->is_main_query() // Doar interogarea principală
        && $q->is_search() // Doar pagina de căutare
    ) {
        // Obține termenii de căutare
        $search_terms = $q->get( 's' );

        // Setează 404 dacă s este gol
        if ( !$search_terms ) {
            add_action( 'wp', function () use ( $q )
            {
                $q->set_404();
                status_header(404);
                nocache_headers();
            });
        }
    }
});
4 feb. 2016 18:48:04
Comentarii

Mulțumesc pentru răspuns - este foarte ciudat, deoarece site-ul are aproximativ 15 pagini și returnează doar 5, iar cele 5 pe care le returnează sunt cu adevărat aleatorii. Încă nu am testat codul tău, deoarece nu sunt lângă un computer, dar când ajung la unul, o voi încerca - practic, am vrut să returneze pagina 404 așa cum ai sugerat, deoarece aceasta este singura pagină cu formularul de căutare.

Stephen Stephen
4 feb. 2016 19:13:48

Destul de ciudat, pe instalarea mea locală returnează toate articolele din toate tipurile de postări. Dar oricum, WP_Query este destul de haotic de lucrat și uneori se comportă destul de ciudat. ;-). Ia-ți timp și testează acest lucru pe deplin și anunță-mă dacă găsești vreun bug. Distracție plăcută ;-)

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

Știu că este foarte ciudat, chestia este că am aproximativ 7 pagini, iar unele au pagini copil și problema este că nu returnează doar paginile părinte, ci returnează 2 pagini părinte și apoi 3 pagini copil. Voi testa și te voi anunța, mulțumesc pentru răspunsul tău :)

Stephen Stephen
4 feb. 2016 19:19:23

Ce e uimitor e că de fiecare dată când închid pagina și o deschid din nou, apoi fac o căutare goală, returnează pagini diferite xD Am adăugat codul tău în functions.php și a funcționat perfect, doar că rămâne pe Pagina 404 - ar exista vreo modalitate de a afișa un titlu diferit în loc de 404, ceva gen "Căutarea ta nu a fost găsită"? Mulțumesc pentru ajutor, Pieter :)

Stephen Stephen
4 feb. 2016 20:03:15

O să fac asta după ce încerc să rezolv singur și Google nu-mi dă niciun răspuns la asta xD

Stephen Stephen
4 feb. 2016 20:06:34
0

Dacă doriți să excludeți șirurile de căutare mai scurte decât o lungime definită și, de asemenea, șirul de căutare gol, puteți utiliza această funcție modificată bazată pe soluția lui birgire. În acest exemplu, căutările goale sau cele cu o singură literă nu vor returna rezultate:

    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

Dacă utilizați fișierul standard search.php, este mult mai ușor să adăugați logica în condiția if ( have_posts())...

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

În acest fel, dacă parametrul de căutare este gol, nu se execută bucla de conținut.

11 ian. 2021 19:44:38
Comentarii

Mult mai ușor de implementat decât soluția cu add_filter, și funcționează perfect și cu un search.php personalizat.

fbmd fbmd
12 mar. 2021 11:40:59

Aceasta poate cauza unele pluginuri să funcționeze incorect. 1) În primul rând, există numeroase hook-uri în timp ce pagina de căutare începe să funcționeze. Unele pluginuri lucrează cu interogarea bazei de date, iar interogarea principală returnează rezultate (toate articolele) când utilizatorul introduce o căutare goală. 2) În al doilea rând, unele pluginuri care lucrează cu primul proces se pot confunda când interogarea principală returnează rezultate, dar pagina de rezultate nu afișează niciun rezultat, ceea ce face ca pluginurile să funcționeze incorect.

vee vee
8 mai 2024 11:32:13
0

Pentru a exclude termenii de căutare cu o lungime mai mică decât o valoare definită și șirul de căutare gol, puteți utiliza această funcție modificată a soluției lui birgire:

add_filter( 'posts_search', function( $search, \WP_Query $q )
{
    $sphrase = get_search_query(); // Obține șirul de căutare
    $slen = strlen($sphrase); // Calculează lungimea șirului
    $minlen = 2; // Lungimea minimă acceptată
        if( ! is_admin() && $slen < $minlen && $q->is_search() && $q->is_main_query() ){
            $search .=" AND 0=1 "; // Adaugă condiție care întotdeauna va fi falsă
        }
    return $search;
}, 10, 2 );
11 iul. 2020 08:22:13
0

Adăugând la răspunsul lui Chad, poți de asemenea să previi căutările cu doar spații, care pentru mine returnau și ele rezultate:

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