4

I am trying to sort my custom post type columns in the admin area. There's two ways I found to do this:

At first this was my way to do it, however I got some strange behaviours. If a meta value is not set, the filter will remove the post from the list, rather than sorting it.

add_filter('request', array($this, 'sort_columns') );
public function sort_columns( $vars ) { 
    if ( isset( $vars['orderby'] ) && 'startdate' == $vars['orderby'] ) {
        $vars = array_merge( $vars, array(
            'meta_key' => '_start_event_datetime',
            'orderby' => 'meta_value_num'
        ) );
    }
}

Hoping to solve this strange behaviour I came across another way to do it, but I got the same behaviour.

add_action('pre_get_posts', array($this, 'sort_columns') );
public function sort_columns( $query ) { 
    $orderby = $query->get( 'orderby');  

    if( 'startdate' == $orderby ) {  
        $query->set('meta_key' , '_start_event_datetime');  
        $query->set('orderby' , 'meta_value_num');  
    }  
}

How do I get my posts that have no meta value set to be sorted instead of removed?

7
  • I really only loosely remember that there was some filter inside the list table class... – kaiser Mar 5 '14 at 21:00
  • That class is marked as private and therefor not intended for use by developers according to codex.wordpress.org/Class_Reference/WP_List_Table – Scuba Kay Mar 5 '14 at 21:04
  • Can I use the posts_orderby hook? – Scuba Kay Mar 5 '14 at 21:08
  • It's marked as private, but you can use it. If something should really be private, then it would be private. But even then I wouldn't give much about it in WP context. – kaiser Mar 5 '14 at 21:10
  • 2
    You can't effectively order some posts by 'meta_value' if not all posts has the related meta key (even if the meta value is null), that's how SQL in WordPress works. Even if you use 'posts_orderby' you'll not able to do the trick. That can be done using a very custom SQL query, but the only reliable way you to do the trick is to force all posts for that CPT to have the meta key you want to order for. This can be done hooking 'save_post' or similar hook and if the post has not a '_start_event_datetime' field set it, maybe setting value to 0. – gmazzap Mar 6 '14 at 2:02
5

The problem is that by setting the posts to be ordered by _start_event_datetime you're creating the implicit assumption that the post will have that meta. This means the SQL query WordPress generates will only fetch posts of your custom post type with that meta.

There are two possible solutions to this:

  • Replace your current query with a slightly more complex meta query
  • Modify the SQL query to use an Outer Join rather than an Inner Join

I'll show you how to do the first as it's the most sensible way of doing this. The second option would make sense for more advanced sorting like sorting by multiple meta keys or taxonomies I'd recommend using the posts_clauses hook and looking into this blog post.

Using a meta query:

$query->set('meta_query',array(
    'relation'  => 'OR',
    array(
        'key'       => '_start_event_datetime',
        'compare'   => 'EXISTS'
    ),
    array(
        'key'       => '_start_event_datetime',
        'compare'   => 'NOT EXISTS',
        'value'     => 'bug #23268' // Allows WP-Librarian to run on pre-3.9 WP installs
    )
));
$query->set('orderby',   'meta_value_num');

This query gets all posts with or without the meta key. Note that the value for the NOT EXISTS condition is completely abritrary and is only there because of a bug in pre-3.9 WordPress.

1
  • But what about when sorting a custom column on the users table in the admin area? – Andrew Truckle Nov 5 '19 at 17:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.