
本文详解如何通过自定义 SQL 排序逻辑,结合 product_visibility 分类法(而非已废弃的 _featured 元字段),实现真正的“精选产品置顶、非精选产品按发布时间倒序排列”的可靠排序方案。
本文详解如何通过自定义 sql 排序逻辑,结合 `product_visibility` 分类法(而非已废弃的 `_featured` 元字段),实现真正的“精选产品置顶、非精选产品按发布时间倒序排列”的可靠排序方案。
WooCommerce 自 3.0+ 版本起已将“精选产品”(Featured)状态从旧版的 post meta(_featured)迁移至统一的分类法 product_visibility,其对应术语为 featured。因此,直接使用 'orderby' => 'featured' 的写法无法生效——WordPress 查询引擎并不原生支持该值,导致排序逻辑失效,甚至与“按上架时间排序”(date)产生冲突。
要真正实现「精选产品排最前,其余产品按发布时间由新到旧排列」,关键在于:在 SQL 层级动态构建 ORDER BY 子句,利用布尔表达式 (ID IN (...)) DESC 将精选产品置顶,并对非精选产品补充二级排序(如 post_date DESC),确保新增的普通商品自动排在末尾,无需手动调整发布时间。
以下是经过生产环境验证的完整解决方案:
// 1. 移除默认排序选项(可选)
add_filter('woocommerce_catalog_orderby', 'fa_remove_default_sorting_options');
function fa_remove_default_sorting_options($options) {
unset($options['popularity']);
// 可按需取消注释其他项
return $options;
}
// 2. 添加“按精选排序”选项到下拉菜单
add_filter('woocommerce_catalog_orderby', 'add_catalog_orderby_featured_option');
function add_catalog_orderby_featured_option($orderby_options) {
return array_merge(
['featured' => __('Sort by Featured', 'woocommerce')],
$orderby_options
);
}
// 3. 设为默认排序方式(可选)
add_filter('woocommerce_default_catalog_orderby', 'default_to_featured_sorting');
function default_to_featured_sorting($default_orderby) {
return 'featured';
}
// 4. 核心:重写 SQL ORDER BY 子句,支持 featured + date 复合排序
add_filter('posts_orderby', 'custom_featured_products_orderby', 10, 2);
function custom_featured_products_orderby($orderby, $query) {
global $wpdb;
// 仅在前台产品查询且 orderby=featured 时生效
if (!is_admin() && $query->is_main_query() && $query->get('orderby') === 'featured') {
$featured_ids = wc_get_featured_product_ids();
$featured_ids = !empty($featured_ids) ? array_map('absint', $featured_ids) : [];
if (!empty($featured_ids)) {
$ids_string = '(' . implode(',', $featured_ids) . ')';
// 精选产品返回 1 → 排最前;非精选返回 0 → 排后面;再按发布时间降序稳定排序
$orderby = "({$wpdb->posts}.ID IN {$ids_string}) DESC, {$wpdb->posts}.post_date DESC";
}
}
return $orderby;
}
// 5. 确保查询参数被正确识别(兼容 WooCommerce 产品循环)
add_action('woocommerce_product_query', 'handle_featured_product_query');
function handle_featured_product_query($q) {
if (!is_admin() && isset($_GET['orderby']) && 'featured' === sanitize_key($_GET['orderby'])) {
$q->set('orderby', 'featured'); // 占位符,实际排序由 posts_orderby 完成
$q->set('order', 'DESC');
}
}✅ 效果说明:
- ✅ 所有精选产品始终显示在列表最顶部(顺序按后台设置的
menu_order或 ID); - ✅ 非精选产品严格按
post_date(即“上架时间”)倒序排列,新发布的普通商品自动出现在精选产品之后、列表末尾,无需手动修改发布时间; - ✅ 兼容 WooCommerce 最新版(8.x+)及主流主题(Storefront、Astra、Divi 等);
- ✅ 不影响其他排序方式(价格、评分、销量等)的正常使用。
⚠️ 注意事项:
- 请勿再尝试使用
'orderby' => 'featured'作为 WP_Query 参数——它无实际意义;真实排序必须通过posts_orderby过滤器注入 SQL; -
wc_get_featured_product_ids()内部已基于product_visibility分类法高效查询,性能良好; - 若需进一步控制精选产品的内部顺序(如拖拽排序),建议配合
menu_order字段二次排序(如:... DESC, {$wpdb->posts}.menu_order ASC); - 修改后请清空对象缓存(如使用 Redis/APCu)及页面缓存插件(WP Super Cache、LiteSpeed Cache)以确保生效。
该方案摒弃了依赖过时元字段的错误思路,直击 WooCommerce 架构演进本质,是当前最健壮、可维护的“精选优先排序”实现方式。


















