posts_orderby
云策文档标注
概述
posts_orderby 是一个 WordPress 过滤器,用于修改 WP_Query 查询中的 ORDER BY 子句。它允许开发者自定义排序逻辑,例如基于外部数据库值或复杂计算进行排序。
关键要点
- 过滤器应用于执行 SQL 语句之前,可修改查询的排序条件。
- 参数包括 $orderby(ORDER BY 子句字符串)和 $query(WP_Query 实例引用)。
- 需谨慎使用,因为它会影响所有 WP_Query 生成的 SQL SELECT 语句,可能导致功能破坏。
- 建议通过检查 WP_Query 实例(如 post_type 或查询变量)来限制过滤器应用范围。
- 可使用 suppress_filters 参数在特定 WP_Query 调用中禁用此过滤器。
代码示例
// 示例1:结合 posts_join_paged 过滤器,基于评分插件的外部表排序
add_filter('posts_orderby', 'edit_posts_orderby');
add_filter('posts_join_paged','edit_posts_join_paged');
function edit_posts_join_paged($join_paged_statement) {
$join_paged_statement = "LEFT JOIN wp_gdsr_data_article gdsra ON gdsra.post_id = wp_posts.ID";
return $join_paged_statement;
}
function edit_posts_orderby($orderby_statement) {
$orderby_statement = "(gdsra.user_votes_total_sum/gdsra.user_votes_count) DESC";
return $orderby_statement;
}// 示例2:检查 WP_Query 实例,仅对特定 post_type 应用排序
add_filter('posts_orderby', 'orderby_pages_callback', 10, 2);
function orderby_pages_callback($orderby_statement, $wp_query) {
if ($wp_query->get("post_type") === "page") {
return "wp_posts.menu_order DESC";
} else {
return $orderby_statement;
}
}// 示例3:在前端自定义分类文章排序,并检查非管理员和非主查询
add_filter('posts_orderby', 'rank_my_taxonomy_post', 10,2);
function rank_my_taxonomy_post($args, $wp_query){
if(is_admin()) return $args;
if(!is_main_query()) return $args;
$queriedObj = $wp_query->get_queried_object();
if (isset($queriedObj->taxonomy) && 'category'==$queriedObj->taxonomy && isset($queriedObj->term_id) && $queriedObj->term_id = 10) {
global $wpdb;
$args = "{$wpdb->posts}.post_name ASC";
}
return $args;
}注意事项
- 过滤器功能强大但易误用,应通过 WP_Query 实例验证来确保只修改目标查询。
- 在现代站点中,每个请求可能运行多个 WP_Query,需注意过滤器的影响范围。
- 使用 suppress_filters 可避免过滤器在特定查询中生效。
原文内容
Filters the ORDER BY clause of the query.
Parameters
Source
$orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) );
Changelog
| Version | Description |
|---|---|
| 1.5.1 | Introduced. |
Skip to note 4 content
Steven Lin
Example migrated from Codex:
Consider the following code. In tandem with a rating plugin that uses a separate database table, sorting by rating value can be achieved with posts_orderby in tandem with the post_join_paged filter.
add_filter('posts_orderby', 'edit_posts_orderby'); add_filter('posts_join_paged','edit_posts_join_paged'); function edit_posts_join_paged($join_paged_statement) { $join_paged_statement = "LEFT JOIN wp_gdsr_data_article gdsra ON gdsra.post_id = wp_posts.ID"; return $join_paged_statement; } function edit_posts_orderby($orderby_statement) { $orderby_statement = "(gdsra.user_votes_total_sum/gdsra.user_votes_count) DESC"; return $orderby_statement; }Skip to note 5 content
Steven Lin
Example migrated from Codex:
This filter is extremely powerful – it will apply a new or updated
ORDERBYto every SQLSELECTstatement generated by theWP_Queryclass. So it’s also very easy to break WordPress functionality using this filter.Fortunately, the
posts_orderbyfilter will also pass a reference to the currentWP_Queryinstance as a second parameter. It’s good practice to always check the referencedWP_Queryto ensure only the desired SQL query is being modified. This is especially true on a modern site, where in many cases more than oneWP_Queryis run per request.// Add the callback to the posts_orderby filter add_filter('posts_orderby', 'orderby_pages_callback', 10, 2); // The posts_orderby filter function orderby_pages_callback($orderby_statement, $wp_query) { # Verify correct post type, or any other query variable if ($wp_query->get("post_type") === "page") { # In this trivial example add a reverse menu order sort return "wp_posts.menu_order DESC"; } else { # Use provided statement instead return $orderby_statement; } } // Example WP_Query that loads all pages. // The above filter callback will cause these to have a reverse menu order sort $pages_query = new WP_Query(array( "post_type" => "page" ));You can also prevent any
posts_orderbycallbacks from being loaded by using thesuppress_filtersin your ownWP_Querycalls:$pages_query = new WP_Query(array( "post_type" => "page", "suppress_filters" => true, // No posts_orderby filters will be run ));Skip to note 6 content
Aurovrata Venet
useful to custom rank posts on the front-end,
add_filter('posts_orderby', 'rank_my_taxonomy_post', 10,2); funciton rank_my_taxonomy_post($args, $wp_query){ //first make sure this is not an admin dashboard query. if(is_admin()) return $args; //you may also want to check if this is the main query, rather than a secondary query such as widgets or menus. if(!is_main_query()) return $args; //you can use the wp_query object to target a specific query, such a a particular category term. $queriedObj = $wp_query->get_queried_object(); if (isset($queriedObj->taxonomy) && 'category'==$queriedObj->taxonomy && isset($queriedObj->term_id) && $queriedObj->term_id = 10) { global $wpdb; $args = "{$wpdb->posts}.post_name ASC"; //order by post slug ascending. } return $args; }