¿Cómo añadir el SKU de WooCommerce a la consulta de búsqueda?
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.

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

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"

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

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