最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

wp query - Can I alter the main loop to 'orderby' a custom callback?

programmeradmin1浏览0评论

I have a custom post type where the title is a name, and I want to sort the loop by the last word in title, the surname.

I can easily break the names apart and filter by the last word in a custom query, but I don't want to re-write the main loop / pagination for the archive page. Is it possible to pass a callback to the orderby param in the action pre_get_posts or is this a lost cause?

Thanks!

I have a custom post type where the title is a name, and I want to sort the loop by the last word in title, the surname.

I can easily break the names apart and filter by the last word in a custom query, but I don't want to re-write the main loop / pagination for the archive page. Is it possible to pass a callback to the orderby param in the action pre_get_posts or is this a lost cause?

Thanks!

Share Improve this question asked Aug 4, 2020 at 4:19 jamesfactsjamesfacts 17711 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

No you can't pass a callback function. Callback functions are PHP, so they can't be run in MySQL. For that to work it would need to query the results from the database first, but you'd get the wrong results because they're unsorted.

You would need to use the posts_orderby filter to do this as part of the SQL query:

add_filter(
    'posts_orderby',
    function( $orderby, $query ) {
        if ( ! is_admin() && $query->is_post_type_archive( 'post_type_name' ) ) {
            $orderby = "SUBSTRING_INDEX(post_title, ' ', -1) ASC, post_title ASC";
        }
        
        return $orderby;
    },
    10,
    2
);

That uses the SUBSTRING_INDEX() MySQL function to order results by everything after the first last space in the post title, and then by the post title so that results with matching surnames are sorted by first name.

Just posting my code for posterity, I made some small changes to @Jacob Peatite's code, if anyone needs a drop-in solution:

add_filter('posts_orderby', __NAMESPACE__ . '\surname_orderby', 10, 2);
function surname_orderby($args, $wp_query)
{
    //make sure this is not an admin dashboard query.
    if (is_admin()) {
        return;
    }
    //check if this is the main query, rather than a secondary query such as widgets or menus.
    if (!is_main_query()) {
        return;
    }

    // the wp query at this filter is literally just the orderby value, we need to fetch the queried object
    $queriedObj = $wp_query->get_queried_object();
    
    if (isset($queriedObj->name) && $queriedObj->name === the_one_I_want ) {
        $args = "SUBSTRING_INDEX(post_title, ' ', -1) ASC, post_title ASC";
        return $args;
    }
}
发布评论

评论列表(0)

  1. 暂无评论