Come aggiungere lo SKU WooCommerce alla query di ricerca?

2 set 2020, 17:15:14
Visualizzazioni: 20K
Voti: 4

Ho un problema nell'aggiungere il meta_value nella query di ricerca per lo SKU di WooCommerce. Di default, la ricerca per SKU funziona solo nell'admin.

Vorrei far accettare la ricerca SKU anche nel frontend.

Nota: Gli SKU non sono presenti nel titolo del prodotto. Quindi devo creare una query personalizzata.

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

Il problema: Quando inserisco questo codice e stampo la richiesta SQL corrente, mi restituisce qualcosa del genere.

    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

Come potete vedere, cerca di recuperare la "parte classica" nella tabella x_posts per post_title O post_excerpt O post_content E deve avere un meta_value del mio SKU.

Come detto sopra, i titoli dei miei prodotti non contengono lo sku.

Obiettivo: Poter cercare nei titoli, excerpt, contenuto o nel meta_value OPPURE cercare esclusivamente con il meta_value.

12
Commenti

Perché stai usando un filtro e me_replace_and_with_or per la tua meta query invece di usare il parametro relation impostato su OR? È estremamente insolito. Tieni presente che gli allegati non compaiono nella ricerca di WordPress di default, devono essere aggiunti esplicitamente alla ricerca in qualche modo

Tom J Nowell Tom J Nowell
2 set 2020 18:03:43

Sto solo cercando di capire perché OR restituisce ancora AND nella query.

Patrice Poliquin Patrice Poliquin
2 set 2020 18:16:59

Posso vedere che dalla tua domanda, ma la presenza del filtro SQL è una parte fondamentale che non può essere ignorata o trascurata, ed è estremamente critica. È direttamente correlato a questo, ed è la parte più sospetta del tuo codice e la causa più probabile del tuo problema. Dobbiamo sapere cosa fa e perché è lì per rispondere alla domanda.

Tom J Nowell Tom J Nowell
2 set 2020 18:18:32

Per impostazione predefinita, gli SKU di WooCommerce non sono inclusi nella query di ricerca sul frontend (solo nel backend). Voglio che gli utenti sul frontend possano cercare per SKU (meta_key _sku). Ma quando eseguo una query di ricerca "standard", restituisce il codice sopra. Sto cercando di modificare la query di ricerca per includere anche il valore meta. Inoltre, non sono interessato a utilizzare un plugin.

Patrice Poliquin Patrice Poliquin
2 set 2020 18:20:36

Capisco, comunque non hai bisogno del filtro SQL per quello, meta_query già lo fa. Tieni anche presente che le raccomandazioni di plugin sono fuori tema qui, chiedere un plugin porterebbe alla chiusura della tua domanda come fuori tema.

Tom J Nowell Tom J Nowell
2 set 2020 18:22:16

Non sono sicuro di capire cosa stai dicendo. Se eseguo una semplice query di ricerca, cerca solo nella tabella x_posts per post_title OPPURE post_excerpt OPPURE post_content.

Patrice Poliquin Patrice Poliquin
2 set 2020 18:24:37

È proprio per questo che esiste pre_get_posts, ed è il motivo per cui aggiungi meta_query. Avresti dovuto chiedere come includere nei risultati di ricerca i post con un meta valore, non come escludere gli allegati dalla ricerca. La maggior parte delle persone vedrà il titolo e troverà una soluzione basata sulla rimozione di attachment dall'array post_type, che non è quello che stai cercando di fare

Tom J Nowell Tom J Nowell
2 set 2020 18:27:01

Ho capito! Comunque, usare meta_query in pre_get_posts ancora non funziona perché la condizione AND rompe tutto. Sembra che il mio relation => 'OR' non stia funzionando.

Patrice Poliquin Patrice Poliquin
2 set 2020 18:29:15

Tuttavia sospetto fortemente che quello che vuoi letteralmente e quello che vuoi effettivamente non siano la stessa cosa. Hai letteralmente chiesto come cercare nei meta dei post. Ma questo significa che se un post menziona lo SKU nel titolo, ma non nei meta del post, non apparirà nei risultati di ricerca. Sospetto che in realtà tu voglia che appaia comunque, è così?

Tom J Nowell Tom J Nowell
2 set 2020 18:29:18

Inoltre, relation si riferisce alle varie clausole della meta query, ma hai solo una singola clausola, quindi il parametro relation è inutile in questa situazione. Puoi spiegare meglio cosa intendi con relation? È (la chiave meta del post è uguale a SKU) OPPURE (????)

Tom J Nowell Tom J Nowell
2 set 2020 18:30:34

Se l'obiettivo è poter cercare post che non menzionano lo SKU, ma hanno quello SKU nei loro meta dati, E post che menzionano lo SKU ma non hanno quello SKU nei loro meta dati, allora la risposta è che questo non può essere fatto con WP_Query. Per quel tipo di funzionalità hai bisogno di una soluzione di ricerca personalizzata, molto probabilmente qualcosa di simile a Elastic Search. Devi anche essere molto, molto chiaro e molto specifico su ciò che vuoi quando chiedi. Nel frattempo, aggiorna la tua domanda in modo da chiedere ciò che vuoi, non come riparare la soluzione rotta.

Tom J Nowell Tom J Nowell
2 set 2020 18:36:41

Ho provato ad aggiornare la domanda e il mio processo. Spero che sarà più chiaro.

Patrice Poliquin Patrice Poliquin
2 set 2020 18:38:10
Mostra i restanti 7 commenti
Tutte le risposte alla domanda 3
3

Se stai utilizzando la ricerca di WordPress puoi aggiungere questo codice per farla funzionare

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
Commenti

Grazie per aver condiviso questo codice. Volevo solo farti sapere che ho provato a utilizzarlo ma genera un avviso PHP: "Parameter 2 to search_by_sku() expected to be a reference, value given"

JulienVan JulienVan
4 feb 2022 09:33:38

@JulienVan come lo stai chiamando?

AHSAN KHAN AHSAN KHAN
10 ago 2022 13:46:22

Meglio tardi che mai, ma se rimuovi la "&" in "&$query_vars", eliminerai l'avviso "expected to be a reference, value given"

TIIUNDER TIIUNDER
16 ott 2024 20:16:25
0

Non ho abbastanza reputazione, quindi non ho potuto commentare, ma ecco la modifica;

Il codice di @ahsankhan sembra funzionare, ma come segnalato, dava un errore "parameter 2".

Se rimuovi il "&" dalla prima riga dove c'è "&$query_vars" e lo sostituisci con semplicemente "$query_vars", sembra funzionare senza generare errori.

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 dic 2022 03:18:57
0
// modificato per la ricerca tramite SKU nelle varianti ;)

function search_by_sku($search, &$query_vars)
{
    global $wpdb;
    if (isset($query_vars->query['s']) && !empty($query_vars->query['s'])) {
        // prodotti semplici
        $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;
        }


        // varianti
        $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 ago 2023 15:08:05