Căutarea goală returnează toate postările
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>

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 );

@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 ;-)

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

@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 :)

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

@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);
.

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.

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

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 articoleleTransmiterea unui termen invalid către un
tax_query
sau utilizarea câmpuluiname
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();
});
}
}
});

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.

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ă ;-)

Ș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 :)

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

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 );

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

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.

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 );
