Cum să implementezi căutare avansată în WordPress

26 oct. 2016, 05:24:21
Vizualizări: 1.05K
Voturi: 1

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:

Interfață căutare avansată WordPress

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.

1
Comentarii
  1. da, este posibil. 2. Întrebările ar trebui să fie despre cod sau concepte de bază, nu are rost să pui întrebări teoretice generale deoarece răspunsul este de obicei scurt și nu foarte util
Mark Kaplun Mark Kaplun
26 oct. 2016 05:41:20
Toate răspunsurile la întrebare 1
7

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>
26 oct. 2016 05:53:21
Comentarii

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

hguser hguser
26 oct. 2016 06:17:38

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.

cybmeta cybmeta
26 oct. 2016 06:40:33

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

hguser hguser
26 oct. 2016 06:49:33

Desigur, nu l-am testat, doar am scris aici. Am rezolvat.

cybmeta cybmeta
26 oct. 2016 06:58:23

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

hguser hguser
26 oct. 2016 07:12:17

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

cybmeta cybmeta
26 oct. 2016 10:59:06

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

hguser hguser
27 oct. 2016 00:47:14
Arată celelalte 2 comentarii