如何通过WP_Query实现WooCommerce商品标题或SKU模糊匹配查询?
WooCommerce 商品标题或SKU模糊匹配查询方案
问题说明
需要通过WP_Query实现WooCommerce商品的标题或SKU模糊匹配,比如输入timb时,匹配标题含Timber chair或SKU含M-TIMB的商品。但之前的组合参数会返回同时满足标题和SKU匹配的结果(AND逻辑),而非任一条件满足即可(OR逻辑)。
原因分析
WP_Query中,s参数(标题/内容搜索)和meta_query默认是AND关系,即使meta_query内部设置了relation => 'OR',也仅作用于meta_query组内的条件,无法改变s和meta_query之间的AND逻辑。
正确解决方案
通过WordPress的posts_join和posts_where钩子,手动构建SQL查询的OR逻辑,将标题匹配与SKU匹配的条件用OR连接:
步骤1:设置基础查询参数
$search = 'timb'; // 你的搜索关键词 $args = [ 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => 20, 'fields' => 'ids', // 仅获取ID优化性能 'no_found_rows' => true, // 不需要分页计数时开启,进一步优化 ];
步骤2:添加钩子修改查询逻辑
add_filter('posts_join', function($join, $query) use ($search) { global $wpdb; // 仅在目标查询中执行 if ($query->get('post_type') === 'product' && !empty($search)) { $join .= " LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_sku'"; } return $join; }, 10, 2); add_filter('posts_where', function($where, $query) use ($search) { global $wpdb; if ($query->get('post_type') === 'product' && !empty($search)) { // 转义关键词避免SQL注入 $escaped_search = $wpdb->esc_like($search); // 构建OR条件:标题模糊匹配 或 SKU模糊匹配 $where .= $wpdb->prepare(" AND ({$wpdb->posts}.post_title LIKE %s OR {$wpdb->postmeta}.meta_value LIKE %s)", "%{$escaped_search}%", "%{$escaped_search}%"); } return $where; }, 10, 2);
步骤3:执行查询并移除钩子
$products_query = new WP_Query($args); $matching_product_ids = $products_query->posts; // 移除钩子,避免影响后续其他查询 remove_filter('posts_join', '__return_empty_string'); remove_filter('posts_where', '__return_empty_string');
替代方案:用meta_query模拟标题查询
如果不想用钩子,可将标题查询转为虚拟的meta条件,再通过钩子替换为实际的post_title字段查询:
$search = 'timb'; $args = [ 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => 20, 'fields' => 'ids', 'meta_query' => [ 'relation' => 'OR', [ 'key' => '_sku', 'value' => $search, 'compare' => 'LIKE' ], [ 'key' => 'post_title', // 虚拟key,需钩子替换 'value' => $search, 'compare' => 'LIKE' ] ] ]; add_filter('posts_where', function($where) { global $wpdb; // 将meta_query中的虚拟post_title条件替换为实际字段查询 return str_replace("{$wpdb->postmeta}.meta_key = 'post_title' AND {$wpdb->postmeta}.meta_value LIKE", "{$wpdb->posts}.post_title LIKE", $where); }); $products_query = new WP_Query($args); remove_filter('posts_where', '__return_empty_string');
为什么之前的方法无效?
- 第一种组合参数:
s和meta_query默认是AND关系,要求标题匹配且SKU匹配 - 第二种修改的参数:
title_filter不是WP_Query的原生参数,无法生效
内容的提问来源于stack exchange,提问作者Petras
相关产品推荐
相关产品推荐

