Cum adaugi SKU WooCommerce în căutare?

2 sept. 2020, 17:15:14
Vizualizări: 20K
Voturi: 4

Am o problemă la adăugarea câmpului meta_value în interogarea de căutare pentru SKU-ul WooCommerce. Implicit, căutarea după SKU funcționează doar în admin.

Aș dori să fac căutarea din frontend să accepte și SKU în căutare.

Notă: SKU-urile nu sunt în titlul produsului. Deci trebuie să creez o interogare personalizată.

function SearchFilter($query) {

  if ($query->is_search) {

    $meta_query_args = array(
      'relation' => 'OR',
      array(
        'key' => '_sku',
        'value' => $query->query_vars['s'],
        'compare' => '=',
      )
    );

    $query->set('post_type', array('post','page', 'product'));
    $query->set('post_status', array('publish'));
    $query->set('meta_query', $meta_query_args);
  }
  
  return $query;

}
add_filter('pre_get_posts','SearchFilter');

Problema: Când pun acest cod și afișez interogarea SQL curentă, îmi returnează ceva de genul acesta.

    SELECT SQL_CALC_FOUND_ROWS  bhd_posts.ID FROM bhd_posts  INNER JOIN bhd_postmeta ON ( bhd_posts.ID = bhd_postmeta.post_id ) WHERE 1=1  AND (((bhd_posts.post_title LIKE '%96242-20VH%') OR (bhd_posts.post_excerpt LIKE '%96242-20VH%') OR (bhd_posts.post_content LIKE '%96242-20VH%')))  AND (bhd_posts.post_password = '')  AND ( 
      ( bhd_postmeta.meta_key = '_sku' AND bhd_postmeta.meta_value = '96242-20VH' )
    ) AND bhd_posts.post_type IN ('post', 'page', 'product') AND ((bhd_posts.post_status = 'publish')) GROUP BY bhd_posts.ID ORDER BY bhd_posts.post_title LIKE '%96242-20VH%' DESC, bhd_posts.post_date DESC LIMIT 0, 10

După cum se poate vedea, încearcă să caute partea "clasică" în tabelul x_posts pentru post_title SAU post_excerpt SAU post_content ȘI trebuie să aibă o valoare meta_value a SKU-ului meu.

După cum am menționat mai sus, titlurile produselor mele nu conțin SKU-ul.

Obiectiv: Să pot căuta în titluri, extras, conținut sau în meta_value SAU să caut exclusiv cu meta_value.

12
Comentarii

De ce folosești un filtru și me_replace_and_with_or pentru interogarea ta meta în loc să folosești parametrul relation setat la OR? Este extrem de neobișnuit. Reține că fișierele atașate nu apar în mod implicit în căutarea WordPress, ele trebuie adăugate explicit la căutare într-un fel.

Tom J Nowell Tom J Nowell
2 sept. 2020 18:03:43

Încerc doar să înțeleg de ce OR returnează în continuare AND în interogare.

Patrice Poliquin Patrice Poliquin
2 sept. 2020 18:16:59

Înțeleg asta din întrebarea ta, dar prezența filtrului SQL este o parte majoră care nu poate fi ignorată sau trecută cu vederea și este extrem de importantă. Este direct legată de aceasta și este partea cea mai suspectă din codul tău, precum și cea mai probabilă cauză a problemei tale. Trebuie să știm ce face și de ce este acolo pentru a răspunde la întrebare.

Tom J Nowell Tom J Nowell
2 sept. 2020 18:18:32

În mod implicit, codurile SKU din WooCommerce nu sunt incluse în interogarea de căutare pe frontend (doar pe backend). Doresc ca utilizatorii de pe frontend să poată căuta după SKU (meta_key _sku). Dar când apelez o interogare de căutare "standard", returnează codul de mai sus. Acum încerc să modific interogarea de căutare pentru a adăuga valoarea meta în ea. De asemenea, nu sunt interesat de utilizarea unui plugin.

Patrice Poliquin Patrice Poliquin
2 sept. 2020 18:20:36

Înțeleg, însă nu ai nevoie de filtrul SQL pentru asta, meta_query deja se ocupă de acest lucru. De asemenea, reține că recomandările de pluginuri sunt în afara subiectului aici, solicitarea unui plugin ar duce la închiderea întrebării tale ca fiind off-topic.

Tom J Nowell Tom J Nowell
2 sept. 2020 18:22:16

Nu sunt sigur că înțeleg ce spui. Dacă rulez o interogare simplă de căutare, aceasta caută doar în tabelul x_posts după post_title SAU post_excerpt SAU post_content.

Patrice Poliquin Patrice Poliquin
2 sept. 2020 18:24:37

Dar pentru asta există pre_get_posts, și de aceea adaugi meta_query. Ar fi trebuit să întrebi cum să incluzi în rezultatele de căutare postările cu o valoare meta, nu cum să excludi atașamentele din căutare. Majoritatea oamenilor vor vedea titlul și vor concepe o soluție care elimină attachment din tabloul post_type, ceea ce nu este ceea ce încerci să faci.

Tom J Nowell Tom J Nowell
2 sept. 2020 18:27:01

Înțeleg! Oricum, folosirea meta_query în pre_get_posts încă nu funcționează pentru că condiția AND strică totul. Se pare că relation => 'OR' nu funcționează.

Patrice Poliquin Patrice Poliquin
2 sept. 2020 18:29:15

Cu toate acestea, bănuiesc puternic că ceea ce vrei literalmente și ceea ce vrei de fapt nu sunt același lucru. Ai întrebat literalmente cum să cauți în meta-datelor postării. Dar asta înseamnă că, dacă o postare menționează SKU-ul în titlu, dar nu în meta-datele postării, nu va apărea în căutare. Bănuiesc că de fapt vrei să apară în căutare, este așa?

Tom J Nowell Tom J Nowell
2 sept. 2020 18:29:18

De asemenea, relation se referă la diferitele clauze ale interogării meta, dar tu ai doar o singură clauză, deci parametrul relation este fără sens în această situație. Poți să explici mai detaliat ce înțelegi prin relație? Are asta (cheia meta a postului este egală cu SKU) SAU (????)

Tom J Nowell Tom J Nowell
2 sept. 2020 18:30:34

Dacă scopul este să poți căuta postări care nu menționează SKU-ul, dar au acel SKU în meta-datelor lor, ȘI postări care menționează SKU-ul dar nu au acel SKU în meta-datelor lor, atunci răspunsul este că acest lucru nu poate fi realizat cu WP_Query. Pentru acest tip de funcționalitate ai nevoie de o soluție personalizată de căutare, cel mai probabil ceva similar cu Elastic Search. De asemenea, trebuie să fii foarte, foarte clar și foarte specific în privința a ceea ce dorești atunci când întrebi. Între timp, actualizează-ți întrebarea astfel încât să ceri ceea ce vrei, nu cum să repari soluția defectuoasă.

Tom J Nowell Tom J Nowell
2 sept. 2020 18:36:41

Am încercat să actualizez întrebarea și procesul meu. Sper că va fi mai clar acum.

Patrice Poliquin Patrice Poliquin
2 sept. 2020 18:38:10
Arată celelalte 7 comentarii
Toate răspunsurile la întrebare 3
3

Dacă utilizați funcția de căutare din WordPress, puteți adăuga acest cod pentru a o face să funcționeze

function search_by_sku( $search, &$query_vars ) {
    global $wpdb;
    if(isset($query_vars->query['s']) && !empty($query_vars->query['s'])){
        $args = array(
            'posts_per_page'  => -1,
            'post_type'       => 'product',
            'meta_query' => array(
                array(
                    'key' => '_sku',
                    'value' => $query_vars->query['s'],
                    'compare' => 'LIKE'
                )
            )
        );
        $posts = get_posts($args);
        if(empty($posts)) return $search;
        $get_post_ids = array();
        foreach($posts as $post){
            $get_post_ids[] = $post->ID;
        }
        if(sizeof( $get_post_ids ) > 0 ) {
                $search = str_replace( 'AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode( ',', $get_post_ids ) . ")) OR (", $search);
        }
    }
    return $search;
    
}
    add_filter( 'posts_search', 'search_by_sku', 999, 2 );
20 nov. 2020 13:57:47
Comentarii

Mulțumesc pentru partajarea acestui cod. Doar pentru informare, am încercat codul dar generează un avertisment PHP: "Parameter 2 to search_by_sku() expected to be a reference, value given"

JulienVan JulienVan
4 feb. 2022 09:33:38

@JulienVan cum îl apelezi?

AHSAN KHAN AHSAN KHAN
10 aug. 2022 13:46:22

Mai bine târziu decât niciodată, dar dacă elimini "&" din "&$query_vars", scapi de avertismentul "expected to be a reference, value given"

TIIUNDER TIIUNDER
16 oct. 2024 20:16:25
0

Nu am suficient reputație, așa că nu am putut comenta, dar iată modificarea;

Codul lui @ahsankhan pare să funcționeze, dar după cum s-a raportat, dădea o eroare la "parametrul 2".

Dacă eliminați "&" din prima linie unde se află "&$query_vars" și înlocuiți cu doar "$query_vars", acesta pare să funcționeze fără a arunca erori.

function search_by_sku( $search, $query_vars ) {
global $wpdb;
if(isset($query_vars->query['s']) && !empty($query_vars->query['s'])){
    $args = array(
        'posts_per_page'  => -1,
        'post_type'       => 'product',
        'meta_query' => array(
            array(
                'key' => '_sku',
                'value' => $query_vars->query['s'],
                'compare' => 'LIKE'
            )
        )
    );
    $posts = get_posts($args);
    if(empty($posts)) return $search;
    $get_post_ids = array();
    foreach($posts as $post){
        $get_post_ids[] = $post->ID;
    }
    if(sizeof( $get_post_ids ) > 0 ) {
            $search = str_replace( 'AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode( ',', $get_post_ids ) . ")) OR (", $search);
    }
}
return $search;
}
  add_filter( 'posts_search', 'search_by_sku', 999, 2 );
15 dec. 2022 03:18:57
0
// modificat pentru căutare după SKU în variații ;)

function search_by_sku($search, &$query_vars)
{
    global $wpdb;
    if (isset($query_vars->query['s']) && !empty($query_vars->query['s'])) {
        // produse simple
        $args = array(
            'posts_per_page' => -1,
            'post_type' => 'product',
            'meta_query' => array(
                array(
                    'key' => '_sku',
                    'value' => $query_vars->query['s'],
                    'compare' => 'LIKE'
                )
            )
        );

        $posts = get_posts($args);
        $get_post_ids = array();

        foreach ($posts as $post) {
            $get_post_ids[] = $post->ID;
        }


        // variații
        $args = array(
            'posts_per_page' => -1,
            'post_type' => 'product_variation',
            'meta_query' => array(
                array(
                    'key' => '_sku',
                    'value' => $query_vars->query['s'],
                    'compare' => 'LIKE'
                )
            )
        );

        $posts_variation = get_posts($args);
        
        if (empty($posts_variation) && empty($posts)) return $search;

        foreach ($posts_variation as $post) {
            $get_post_ids[] = $post->post_parent;
        }

        if (sizeof($get_post_ids) > 0) {
            $search = str_replace('AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode(',', $get_post_ids) . ")) OR (", $search);
        }
    }
    return $search;

}

add_filter('posts_search', 'search_by_sku', 999, 2);
18 aug. 2023 15:08:05