¿Cómo añadir el SKU de WooCommerce a la consulta de búsqueda?

2 sept 2020, 17:15:14
Vistas: 20K
Votos: 4

Tengo un problema al añadir el meta_value en la consulta de búsqueda para el SKU de WooCommerce. Por defecto, la búsqueda por SKU solo funciona en el admin.

Me gustaría hacer que la búsqueda en el frontend acepte SKU en la búsqueda.

Nota: Los SKU no están en el título del producto. Por lo tanto, necesito crear una consulta personalizada.

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

El problema: Cuando coloco este código e imprimo la consulta SQL actual, me da algo como esto.

    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

Como pueden ver, intenta buscar la "parte clásica" en la tabla x_posts para post_title O post_excerpt O post_content Y debe tener un meta_value de mi SKU.

Como se mencionó anteriormente, mis títulos de productos no tienen el SKU en ellos.

Objetivo: Tener que buscar en títulos, extracto, contenido o en meta_value O buscar exclusivamente con el meta_value.

12
Comentarios

¿Por qué estás usando un filtro y me_replace_and_with_or para tu meta query en lugar de usar el parámetro relation configurado como OR? Es extremadamente inusual. Ten en cuenta que los adjuntos no aparecen en la búsqueda de WordPress por defecto, tienen que ser añadidos explícitamente a la búsqueda de alguna manera.

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

Solo estoy intentando entender por qué OR sigue devolviendo AND en la consulta.

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

Puedo ver eso en tu pregunta, pero la presencia del filtro SQL es una parte importante que no puede ignorarse o pasarse por alto, y es super crítica. Está directamente relacionado con esto, y es la parte más sospechosa de tu código, y la causa más probable de tu problema. Necesitamos saber qué hace y por qué está ahí para responder a la pregunta.

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

Por defecto, los SKU de WooCommerce no están incluidos en la consulta de búsqueda en el frontend (solo en el backend). Quiero que los usuarios en el frontend puedan buscar por SKU (meta_key _sku). Pero cuando llamo a una consulta de búsqueda "por defecto", devuelve el código mencionado anteriormente. Ahora estoy intentando editar la consulta de búsqueda para agregar el valor meta en ella. Además, no me interesa usar un plugin.

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

Entiendo, pero no necesitas el filtro SQL para eso, meta_query ya hace eso. También ten en cuenta que las recomendaciones de plugins están fuera de tema aquí, pedir un plugin haría que tu pregunta se cerrara por estar fuera de tema.

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

No estoy seguro de entender lo que dices. Si ejecuto una consulta de búsqueda simple, solo busca en la tabla x_posts en post_title O post_excerpt O post_content.

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

Para eso es pre_get_posts, y por eso añades meta_query. Deberías haber preguntado cómo incluir resultados de búsqueda para posts con un valor meta, no cómo excluir adjuntos de la búsqueda. La mayoría verá el título y diseñará una solución para eliminar attachment del array post_type, que no es lo que estás intentando hacer

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

¡Entiendo! De todos modos, usar meta_query en pre_get_posts aún no funciona porque la condición AND rompe todo. Parece que mi relation => 'OR' no está funcionando.

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

Sin embargo, sospecho fuertemente que lo que literalmente quieres y lo que realmente quieres no es lo mismo. Literalmente has preguntado cómo buscar en meta datos de posts. Pero esto significa que si un post menciona el SKU en el título pero no en los meta datos, no aparecerá en la búsqueda. Sospecho que realmente sí quieres que aparezca en la búsqueda, ¿es ese el caso?

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

Además, relation se refiere a las diversas cláusulas de la meta consulta, pero solo tienes una única cláusula, por lo que el parámetro relation no tiene sentido en esta situación. ¿Puedes explicar más a qué te refieres con la relación? ¿Es esto (la clave meta del post es igual a SKU) O (????)

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

Si el objetivo es poder buscar posts que no mencionen el SKU, pero que tengan ese SKU en sus metadatos, Y posts que mencionen el SKU pero no tengan ese SKU en sus metadatos, entonces la respuesta es que esto no se puede hacer con WP_Query. Para ese tipo de funcionalidad necesitas una solución de búsqueda personalizada, muy probablemente algo similar a Elastic Search. También necesitas ser muy, muy claro y muy específico sobre lo que quieres al preguntar. Mientras tanto, actualiza tu pregunta para que preguntes sobre lo que quieres, no sobre cómo arreglar la solución rota.

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

Intenté actualizar la pregunta y mi proceso. Espero que sea más claro.

Patrice Poliquin Patrice Poliquin
2 sept 2020 18:38:10
Mostrar los 7 comentarios restantes
Todas las respuestas a la pregunta 3
3

Si estás utilizando la búsqueda de WordPress puedes agregar este código para hacerla funcionar

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
Comentarios

Gracias por compartir este código. Solo para hacerte saber que lo probé pero genera una advertencia de PHP: "Se esperaba que el parámetro 2 para search_by_sku() fuera una referencia, se proporcionó un valor"

JulienVan JulienVan
4 feb 2022 09:33:38

@JulienVan ¿cómo lo estás llamando?

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

Mejor tarde que nunca, pero si eliminas el "&" en "&$query_vars", te deshaces de la advertencia "se esperaba una referencia, se proporcionó un valor"

TIIUNDER TIIUNDER
16 oct 2024 20:16:25
0

No tengo suficiente reputación, así que no pude comentar, pero aquí está la edición:

El código de @ahsankhan parece funcionar, pero como se reportó, estaba dando un error en el "parámetro 2".

Si eliminas el "&" de la primera línea donde dice "&$query_vars" y lo reemplazas con solo "$query_vars", esto parece funcionar sin generar errores.

function buscar_por_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', 'buscar_por_sku', 999, 2 );
15 dic 2022 03:18:57
0
// modificado para búsqueda por SKU en variaciones ;)

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


        // variaciones
        $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