结果,我不得不使用“posts\\u orderby”过滤器。我转向Sally CJ对我的question 和another question. 我以为我不需要它,但我错了。
帖子没有得到正确排序的原因是,在WP生成的MySQL查询中,Posteta表被多次连接,导致多个meta_key
列。因此,在第一个meta\\u key列中,meta key不是\'tdlrm_mp_\'.$taxonomy_term
, 还有一些其他的meta键,所以帖子只是按照与此列对应的meta值排序,如下所示:
/*
| wp_postmeta.meta_key | wp_postmeta.meta_value | mt1.meta_key | mt1.meta_value |
----------------------------------------------------------------------------------
| tdlrm_mp_1494 | 1 | tdlrm_mp_1494 | 1 |
----------------------------------------------------------------------------------
| tdlrm_mp_1494 | 2 | tdlrm_mp_1494 | 2 |
----------------------------------------------------------------------------------
| some_other_key | X | NULL | NULL |
----------------------------------------------------------------------------------
| some_other_key | Y | NULL | NULL |
----------------------------------------------------------------------------------
*/
为了解决这个问题,我们需要在ORDER BY中添加case语句,这样meta\\u value列将只用于排序实际具有
tdlrm_mp_1494
其中的元键。
我们可以通过设置orderby过滤器来实现这一点。
This is how:
下面是我们的元查询参数。注意
orderby
参数设置为false(我们不需要它)。
$taxonomy = 1494; // for demonstration purposes
$args[\'meta_query\'] = array(
\'relation\' => \'OR\',
\'mp_exists\' => array(
\'key\' => \'tdlrm_mp_\'.$taxonomy,
\'type\' => \'NUMERIC\',
),
\'mp_not_exists\' => array(
\'key\' => \'tdlrm_mp_\'.$taxonomy,
\'compare\' => \'NOT EXISTS\'
)
);
$args[\'orderby\'] = false;
首先,我们向查询参数中添加一个自定义变量,让WP知道在哪里使用过滤器:
$args[\'tdlrm_commands\'] = array(
\'filter\' => \'orderby_filter_1\',
\'key\' => \'tdlrm_mp_\'.$taxonomy
);
其次,我们添加过滤器(到functions.php或插件文件,无论什么):
add_filter( \'posts_orderby\', function ( $orderby, $query ) {
//won\'t fire for other queries
if(
empty($query->query[\'tdlrm_commands\'][\'do\'])
|| $query->query[\'tdlrm_commands\'][\'do\'] !== \'orderby_filter_1\'
)
{
return $orderby;
}
global $wpdb;
$meta_clauses = $query->meta_query->get_clauses();
//get the key we passed in our custom argument
$key = $query->query[\'tdlrm_commands\'][\'key\'];
//get the table alias (remember there are multiple postmeta tables joined together,
//we need only the one that satisfies our meta query clause, `mp_exists`)
$has_tdlrm_mp = $meta_clauses[\'mp_exists\'][\'alias\'];
/*
in the postmeta table with alias {$has_tdlrm_mp},
when meta_key equals to {$key},
use the first clause,
otherwise, use the second.
first clause:
in the postmeta table with alias {$has_tdlrm_mp},
when meta_key equals to {$key},
order by its meta value, in the ascending order
(+0 casts a string to number, otherwise 21 will go after 2 and before 3.)
second clause:
if it\'s not, order by title, in the ascending order
*/
$orderby = " CASE {$has_tdlrm_mp}.meta_key
WHEN \'{$key}\' THEN 1
ELSE 2
END ASC,
CASE {$has_tdlrm_mp}.meta_key
WHEN \'{$key}\' THEN {$has_tdlrm_mp}.meta_value+0
END ASC,
{$wpdb->posts}.post_title ASC";
return $orderby;
}, 10, 2 );