最合适的回答,由SO网友:J.D. 整理而成
不幸的是,尽管WP_Query
支持\'tax_query\'
arg,它不支持基于post术语的订购。因此,您需要像现在这样修改查询SQL。但是,您正在构建ORDER BY
子句不正确,这就是为什么它是按post_date
. 您需要做的是使用CASE
声明如下:
CASE
WHEN (wp_terms.slug LIKE \'downtown\' AND wp_term_taxonomy.taxonomy LIKE \'place\') THEN 1
WHEN (wp_terms.slug LIKE \'abroad\' AND wp_term_taxonomy.taxonomy LIKE \'place\') THEN 0
END
这将根据您分配给每个条款的优先级排序(
1
,
0
, 等等,优先级越高,除非您使用
ASC
而不是
DESC
用于订购)。
因为要独立地对这两个分类法排序,所以需要有两个连接和两个case语句。(例如,请参见下文。)
您还需要引起GROUP BY
在post ID上,为避免重复结果:
$clauses[\'groupby\'] = \'wptests_posts.ID\';
因此,您的最终查询结果如下所示(格式为便于阅读):
SELECT SQL_CALC_FOUND_ROWS wptests_posts.ID FROM wptests_posts
LEFT JOIN (
wptests_term_relationships tr_place,
wptests_term_taxonomy tt_place,
wptests_terms t_place
) ON (
tr_place.object_id = wptests_posts.ID
AND tt_place.term_taxonomy_id = tr_place.term_taxonomy_id
AND tt_place.taxonomy = \'place\'
AND t_place.term_id = tt_place.term_id
)
LEFT JOIN (
wptests_term_relationships tr_pricetag,
wptests_term_taxonomy tt_pricetag,
wptests_terms t_pricetag
) ON (
tr_pricetag.object_id = wptests_posts.ID
AND tt_pricetag.term_taxonomy_id = tr_pricetag.term_taxonomy_id
AND tt_pricetag.taxonomy = \'pricetag\'
AND t_pricetag.term_id = tt_pricetag.term_id
)
WHERE 1=1 AND wptests_posts.post_type = \'course\' AND (wptests_posts.post_status = \'publish\')
GROUP BY wptests_posts.ID
ORDER BY
(CASE
WHEN (t_place.slug LIKE \'downtown\') THEN 1
WHEN (t_place.slug LIKE \'abroad\') THEN 0
END) DESC, (CASE
WHEN (t_pricetag.slug LIKE \'expensive\') THEN 1
WHEN (t_pricetag.slug LIKE \'cheap\') THEN 0
END) DESC,
wptests_posts.post_date DESC
LIMIT 0, 10
下面是一个PHPUnit测试示例,演示了这一点,包括用于生成联接和ORDERBY的示例代码(用于生成上述查询):
class My_Test extends WP_UnitTestCase {
public function test() {
// Create the post type.
register_post_type( \'course\' );
// Create the posts.
$cooking_post_id = $this->factory->post->create(
array( \'post_title\' => \'Cooking\', \'post_type\' => \'course\' )
);
$surfing_post_id = $this->factory->post->create(
array( \'post_title\' => \'Surfing\', \'post_type\' => \'course\' )
);
$building_post_id = $this->factory->post->create(
array( \'post_title\' => \'Building\', \'post_type\' => \'course\' )
);
$hacking_post_id = $this->factory->post->create(
array( \'post_title\' => \'Hacking\', \'post_type\' => \'course\' )
);
// Create the taxonomies.
register_taxonomy( \'place\', \'course\' );
register_taxonomy( \'pricetag\', \'course\' );
// Create the terms.
$downtown_term_id = wp_create_term( \'downtown\', \'place\' );
$abroad_term_id = wp_create_term( \'abroad\', \'place\' );
$expensive_term_id = wp_create_term( \'expensive\', \'pricetag\' );
$cheap_term_id = wp_create_term( \'cheap\', \'pricetag\' );
// Give the terms to the correct posts.
wp_add_object_terms( $cooking_post_id, $downtown_term_id, \'place\' );
wp_add_object_terms( $cooking_post_id, $cheap_term_id, \'pricetag\' );
wp_add_object_terms( $surfing_post_id, $abroad_term_id, \'place\' );
wp_add_object_terms( $surfing_post_id, $expensive_term_id, \'pricetag\' );
wp_add_object_terms( $building_post_id, $downtown_term_id, \'place\' );
wp_add_object_terms( $building_post_id, $expensive_term_id, \'pricetag\' );
wp_add_object_terms( $hacking_post_id, $abroad_term_id, \'place\' );
wp_add_object_terms( $hacking_post_id, $cheap_term_id, \'pricetag\' );
$query = new WP_Query(
array(
\'fields\' => \'ids\',
\'post_type\' => \'course\',
)
);
add_filter( \'posts_clauses\', array( $this, \'filter_post_clauses\' ) );
$results = $query->get_posts();
$this->assertSame(
array(
$building_post_id,
$cooking_post_id,
$surfing_post_id,
$hacking_post_id,
)
, $results
);
}
public function filter_post_clauses( $clauses ) {
global $wpdb;
$clauses[\'orderby\'] = "
(CASE
WHEN (t_place.slug LIKE \'downtown\') THEN 1
WHEN (t_place.slug LIKE \'abroad\') THEN 0
END) DESC, (CASE
WHEN (t_pricetag.slug LIKE \'expensive\') THEN 1
WHEN (t_pricetag.slug LIKE \'cheap\') THEN 0
END) DESC,
" . $clauses[\'orderby\'];
foreach ( array( \'place\', \'pricetag\' ) as $taxonomy ) {
// Instead of interpolating directly here, you should use $wpdb->prepare() for $taxonomy.
$clauses[\'join\'] .= "
LEFT JOIN (
$wpdb->term_relationships tr_$taxonomy,
$wpdb->term_taxonomy tt_$taxonomy,
$wpdb->terms t_$taxonomy
) ON (
tr_$taxonomy.object_id = $wpdb->posts.ID
AND tt_$taxonomy.term_taxonomy_id = tr_$taxonomy.term_taxonomy_id
AND tt_$taxonomy.taxonomy = \'$taxonomy\'
AND t_$taxonomy.term_id = tt_$taxonomy.term_id
)
";
}
$clauses[\'groupby\'] = \'wptests_posts.ID\';
return $clauses;
}
}