0

I know there are a lot of threads about similar issues, but I can't figure out why my custom sort won't work in the category admin page. Here is my code to add the ACF field as a column to the category page and register the sorting ability. For some reason the add_action( 'pre_get_posts', 'category_custom_orderby' ); hook isn't working. Is there something I'm overlooking? Or is there some other way to get the sorting function to work?

add_filter( 'manage_edit-category_columns', 'set_custom_category_columns' );
function set_custom_category_columns( $columns ) {
  $columns['sort_order'] = __( 'Sort Order' );
  return $columns;
}

add_action( 'manage_category_custom_column' , 'custom_category_column', 10, 3 );
function custom_category_column( $string, $column, $term_id ) {
  if ( $column == 'sort_order' ) {
    $category = get_category( $term_id );
    echo get_field('sort_order', $category);
  }
}

function add_sortable_columns( $columns ) {
  $columns['sort_order'] = 'sort_order';
  return $columns;
}
add_filter( 'manage_edit-category_sortable_columns', 'add_sortable_columns');

function category_custom_orderby( $query ) {
  if ( ! is_admin() )
    return;

  $orderby = $query->get( 'orderby');

  if ( 'sort_order' == $orderby ) {
    $query->set( 'meta_key', 'sort_order' );
    $query->set( 'orderby', 'meta_value' );    
  } 
}
add_action( 'pre_get_posts', 'category_custom_orderby' );

1 Answer 1

0

For some reason the add_action( 'pre_get_posts', 'category_custom_orderby' ); hook isn't working.

Yes, and it's because on the Categories admin page (where you can see the Categories list table), the list table uses WP_Term_Query and not WP_Query, hence the above hook (pre_get_posts) is not fired.

So instead of the above add_action(), try using the parse_term_query hook like so:

  • If all of your categories have the sort_order meta,

    add_action( 'parse_term_query', 'my_parse_term_query' );
    function my_parse_term_query( $query ) {
        $args =& $query->query_vars;
    
        if ( is_admin() && 'sort_order' === $args['orderby'] ) {
            $args['meta_key'] = 'sort_order';
            $args['orderby']  = 'meta_value_num';
        }
    }
    
  • If there are categories that do not have the sort_order meta,

    add_action( 'parse_term_query', 'my_parse_term_query' );
    function my_parse_term_query( $query ) {
        $args =& $query->query_vars;
    
        if ( is_admin() && 'sort_order' === $args['orderby'] ) {
            $args['meta_query'] = isset( $args['meta_query'] ) ?
                (array) $args['meta_query'] : array();
    
            $args['meta_query'][] = array(
                'relation'      => 'OR',
                'sort_order'    => array( // include categories that have the meta
                    'key'  => 'sort_order',
                    'type' => 'NUMERIC',
                ),
                'no_sort_order' => array( // and categories that don't have the meta
                    'key'     => 'sort_order',
                    'compare' => 'NOT EXISTS',
                ),
            );
        }
    }
    

And note that I used the $args['orderby'] = 'meta_value_num' and 'type' => 'NUMERIC' because I presumed the meta value is a number?

Also, the =& as in $args =& $query->query_vars means that we're referencing the original $query_vars property in the WP_Term_Query class. So if we modify the $args variable, it means we're actually modifying the original $query_vars property.

1
  • 1
    Perfect! Thank you so much and thanks for the info! Aug 20, 2021 at 4:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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