Как добавить артикул (SKU) WooCommerce в поисковый запрос?
У меня возникла проблема с добавлением meta_value
в поисковый запрос для артикула (SKU) WooCommerce. По умолчанию поиск по SKU работает только в админ-панели.
Я хочу сделать так, чтобы фронтенд-поиск принимал SKU при поиске.
Примечание: SKU нет в заголовке товара. Поэтому мне нужно создать пользовательский запрос.
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');
Проблема: Когда я размещаю этот код и вывожу текущий SQL-запрос, он выглядит примерно так.
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
Как видите, он пытается искать "классическую часть" в таблице x_posts
для post_title
ИЛИ post_excerpt
ИЛИ post_content
И должен иметь meta_value
моего SKU.
Как сказано выше, в заголовках моих товаров нет артикула.
Цель: Иметь возможность искать в заголовках, кратком описании, содержимом или в meta_value ИЛИ искать исключительно по meta_value.

Если вы используете поиск в WordPress, вы можете добавить этот код, чтобы он работал по артикулам (SKU)
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 );

Спасибо за код. Хочу сообщить, что я попробовал его, но он вызывает PHP предупреждение: "Parameter 2 to search_by_sku() expected to be a reference, value given"

Не хватает репутации, поэтому не смог оставить комментарий, но вот исправление:
Код от @ahsankhan вроде бы работает, но, как сообщалось, выдавал ошибку "parameter 2".
Если убрать "&" из первой строки, где "&$query_vars", и заменить на просто "$query_vars", то код начинает работать без ошибок.
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 );

// модифицировано для поиска по артикулу в вариациях товаров ;)
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);
$get_post_ids = array();
foreach ($posts as $post) {
$get_post_ids[] = $post->ID;
}
// вариации товаров
$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);
