首先,我想澄清一下,在正常情况下,没有具体的订单要求,并且假设您是在pre_get_posts
hook,你可以这样做:
add_action(\'pre_get_posts\', function ($query) {
// only perform for a given query
// do your checks and return early
if (! $query->is_main_query() || ! $query->is_home()) {
return;
}
$query->set(\'meta_key\', \'orden_en_categ\');
$query->set(\'orderby\', \'meta_value_num\');
$query->set(\'order\', \'ASC\');
});
根本不需要设置元查询。
然后,要实现最后为空的升序,有不同的方法。假设数据是数字,可以使用减号运算符并按如下顺序降序:
add_filter(\'posts_orderby\', function ($orderby, $query) {
global $wpdb;
// only perform for a given query
// do your checks and return early
if (! $query->is_main_query() || ! $query->is_home()) {
return $orderby;
}
return "-{$wpdb->postmeta}.meta_value DESC";
}, 2, 10);
字母数字值的更通用解决方案可以是:
add_filter(\'posts_orderby\', function ($orderby, $query) {
global $wpdb;
// return early...
return "{$wpdb->postmeta}.meta_value IS NULL, {$wpdb->postmeta}.meta_value ASC";
}, 2, 10);
IS NULL
为空值返回1,为非空值返回0。按升序,0(不是null)将排在第一位。然后我们也按值本身的升序排序。
最后,当使用posts_orderby
过滤器,您不再需要这两行:
$query->set(\'orderby\', \'meta_value_num\');
$query->set(\'order\', \'ASC\');
Edit: 最初的解决方案没有考虑到不存在的元值。去除
meta_key
,
meta_query
,
orderby
和
order
从查询变量
pre_get_posts
并按如下方式过滤查询。
add_filter(\'posts_clauses\', function ($clauses, $query) {
global $wpdb;
if (!$query->is_main_query() || !$query->is_home()) {
return $clauses;
}
$meta_key = \'orden_en_categ\';
$clauses[\'join\'] .= " LEFT JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = \'$meta_key\')";
$clauses[\'where\'] .= " AND ({$wpdb->postmeta}.meta_key = \'$meta_key\' OR {$wpdb->postmeta}.post_id IS NULL)";
$clauses[\'groupby\'] = "{$wpdb->posts}.ID";
$clauses[\'orderby\'] = "-{$wpdb->postmeta}.meta_value+0 DESC";
return $clauses;
}, 2, 10);
几乎是一个完整的自定义查询,但无法找到更好的方法。希望有帮助。
生成的查询类似于:
SELECT wp_posts.ID
FROM wp_posts
LEFT JOIN wp_postmeta
ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = \'orden_en_categ\')
WHERE 1=1
AND wp_posts.post_type = \'post\'
AND (wp_posts.post_status = \'publish\')
AND (wp_postmeta.meta_key = \'orden_en_categ\' OR wp_postmeta.post_id IS NULL)
GROUP BY wp_posts.ID
ORDER BY -wp_postmeta.meta_value+0 DESC
LIMIT 0, 10