Cum să implementezi căutare avansată în WordPress
Am întâmpinat mai multe probleme la crearea temei personalizate WordPress:
1. Evitarea hardcodării URL-ului de căutare în searchform.php
.
Un șablon tipic arată astfel:
<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">Căutare</button>
</form>
Totuși, observați action="<?php echo get_search_link(); ?>
- acțiunea este hardcodată, presupunând că calea de căutare este http://homeurl/?s=xxx
. Dar dacă un plugin modifică calea de căutare la ceva de genul http://homeurl/search?s=xxx
?
2. Modificarea URL-ului de căutare
Nu-mi place calea implicită /?s=xxx
pentru căutare, prefer ceva de genul /search?s=xxx
.
3. Căutare avansată cu mai multe variabile de interogare
Vreau să caut după cuvinte cheie + categorie + etichetă + valoare meta, astfel:
Trebuie să setez URL-ul de căutare pentru fiecare link din panou și să-l evidențiez când este variabila curentă de interogare.
Este posibil acest lucru?
(Problema actualizată a fost postată într-un nou articol aici)
Conform răspunsului lui cybmeta, am făcut următoarele modificări:
add_action('pre_get_posts', 'include_any_post_type_in_search');
function include_any_post_type_in_search($query)
{
// Verifică dacă suntem în admin sau nu este interogarea principală de căutare
if (!is_admin() && $query->is_search && $query->is_main_query()) {
$tax_query = array(
'relation' => 'AND'
);
// Adaugă filtrare după categorie dacă există parametrul 'c'
if (isset($_REQUEST['c'])) {
$cate = $_REQUEST['c'];
array_push($tax_query, array(
'taxonomy' => 'category',
'terms' => sanitize_text_field($cate)
));
}
// Adaugă filtrare după etichetă dacă există parametrul 't'
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);
}
}
// Adaugă variabilele personalizate la interogările WordPress
add_filter('query_vars', 'cyb_query_vars');
function cyb_query_vars($vars)
{
array_push($vars, "t", "c"); // t pentru etichete, c pentru categorii
return $vars;
}
// Funcție pentru generarea URL-urilor de căutare
function my_get_search_url($key, $val)
{
$query = array();
$supported = array("c", "t", "k"); // Parametrii suportați
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));
}
Utilizare:
<?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 } ?>
Generează URL-uri de forma: /search/c%3D9
:
1. c=9
este codificat
2. Se afișează pagina de index în loc de pagina cu rezultatele căutării.
Dacă accesez /?c=9&s=1
obțin rezultate cu cuvântul cheie 1
și categoria 9.
Pentru /?c=9
se afișează pagina de index.
Pentru /search?c=9
primesc eroare 404.
Se pare că există probleme cu rescrierea URL-urilor.

Dacă folosești get_search_link()
și cineva filtrează URL-ul de căutare și îl schimbă, get_search_link()
va returna URL-ul filtrat; acesta este avantajul unui URL care nu este hardcodat. Tu sau un plugin de la terți puteți modifica URL-ul și acesta va returna întotdeauna valoarea corectă. Deci, problemele 1 și 2 par să nu existe.
Problema 3 are abordări diferite:
1.- Folosește input-uri în formularul de căutare cu un name
egal cu un argument de query acceptat direct de WP_Query
în query string. De exemplu, 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="">Toate categoriile</option>
<option value="politics">Politică</option>
<option value="economy">Economie</option>
</select>
<button class="search-submit" type="submit" role="button">Caută</button>
</form>
2.- Folosește orice query string dorești și conectează WP_Query
la cererea de căutare în acțiunea pre_get_posts
:
HTML-ul:
<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="">Toate categoriile</option>
<option value="politics">Politică</option>
<option value="economy">Economie</option>
</select>
<button class="search-submit" type="submit" role="button">Caută</button>
</form>
Și acțiunea:
add_action( 'pre_get_posts', 'cyb_advanced_search' );
function cyb_advanced_search( $query ) {
if ( ! is_admin() && $query->is_search && $query->is_main_query() ) {
// Setează parametrii de query de care ai nevoie
// De exemplu
$search_filter = $_REQUEST[ 'a_search_filter' ];
$tax_query = [
'taxonomy' => 'news',
'field' => 'slug',
'terms' => sanitize_text_field( $search_filter ),
];
$query->set( 'tax_query', $tax_query );
}
}
Aș adăuga query string-ul în sistemul WP Rewrite:
add_filter( 'query_vars', 'cyb_query_vars' );
function cyb_query_vars( $vars ) {
$vars[] = 'a_search_filter';
return $vars;
}
Acum poți folosi get_query_var()
pentru a obține valoarea variabilei de query personalizate:
add_action( 'pre_get_posts', 'cyb_advanced_search' );
function cyb_advanced_search( $query ) {
if ( ! is_admin() && $query->is_search && $query->is_main_query() ) {
// Setează parametrii de query de care ai nevoie
// De exemplu
$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 );
}
}
În final, poți obține cererea curentă și adăuga/elimina clase pentru link-urile tale, evidențiindu-le după preferință cu CSS:
if( get_query_var( 'a_search_filter' ) == 'category1' ) {
$class = 'selected';
}
<a href="..." class=".<?php esc_attr_e( $class ); ?>.">Category 1</a>

Mulțumesc pentru răspunsul detaliat. Și vrei să spui că toți argumentele de interogare acceptate pot fi folosite direct în URL-ul de căutare ca variabile de interogare precum category_name
? Nu am știut niciodată asta :(

Nu toate argumentele de interogare, doar cele acceptate ca șir de interogare. De exemplu, poți folosi https://example.com/?s=cuvant-cheie&category_name=politica
și rezultatele căutării vor căuta cuvant-cheie
în articolele care aparțin categoriei politica
. Din păcate, nu cunosc lista exactă a argumentelor care pot fi folosite direct ca șir de interogare, dar argumentele pe care le vezi în documentație cu formatul key=value
ar trebui să funcționeze, inclusiv post_type
, author
și multe altele.

OK, am înțeles. O să încerc. Apropo, se pare că sunt unele apeluri de funcții inconsistente în codurile tale.

Aproape am reușit să-l fac să funcționeze, cu o singură problemă, am actualizat postarea, poți să verifici dacă este posibil?

Se pare că ai o problemă diferită. Ar fi mai bine dacă ai posta o nouă întrebare și ai include ce face funcția my_get_search_url()
și ce rezultat te aștepți. /?c=9
încarcă indexul și /search?c=9
dă eroare 404 mi se pare corect, decât dacă ai codat un comportament diferit pentru astfel de URL-uri; implicit, WordPress recunoaște o căutare (is_search()
returnează true
) doar dacă variabila de interogare s
este setată (vezi L1646 (WP 4.6) în wp-includes/query.php..

Găsesc că am creat un post nou:http://wordpress.stackexchange.com/q/244088/104900
