Sort WP_User_Query by meta_key value with pre_user_query

I’m trying to order my users by their Member Number – which is a custom meta value. It seems I can’t easily orderby a meta_value. I’ve read a few workarounds but I can’t get my head around it. This is my code so far…

function sort_by_member_number( $vars ) {
    if ( isset( $vars->query_vars['orderby'] ) && 'member-number' == $vars->query_vars['orderby'] ) {
        $vars = array_merge(
            $vars->query_vars, array(
                'meta_key' => 'arcc_member_number'
            )
        );
    }
    return $vars;
}
add_filter( 'pre_user_query', 'sort_by_member_number' );

arcc_member_number is a numeric value – how can I extend this to sort by that value?

Related posts

1 comment

  1. As written, this is unlikely to do anything. If you add a couple of var_dumps like this:

    function sort_by_member_number( $vars ) {
      var_dump($vars);
      if ( isset( $vars->query_vars['orderby'] ) && 'member-number' == $vars->query_vars['orderby'] ) {
          $vars = array_merge(
              $vars->query_vars, array(
                  'meta_key' => 'arcc_member_number'
              )
          );
      }
      var_dump($vars);
      return $vars;
    }
    add_filter( 'pre_user_query', 'sort_by_member_number' );
    

    You will notice that nothing has changed before and after your code, and you won’t find your arrc_member_number value in there anywhere. And, if you look at that dumped data, you will notice that the query has already been constructed (sample query only):

    ["query_fields"]=>
      string(30) "SQL_CALC_FOUND_ROWS wp_users.*"
    ["query_from"]=>
      string(13) "FROM wp_users"
    ["query_where"]=>
      string(9) "WHERE 1=1"
    ["query_orderby"]=>
      string(28) "ORDER BY user_registered ASC"
    ["query_limit"]=>
      NULL
    

    And if you look in the source for where the query actually runs, those are the properties used.

    In other words, pre_user_query does not work like pre_get_posts. You will need to actually parse that query_* values, which can be tricky and means you need to be good with SQL. If you can write your user query to be something like this…

    $user_query = new WP_User_Query( 
      array ( 
        'orderby' => 'arcc_member_number',
        'meta_query' => array(
            array(
                'key'     => 'arcc_member_number',
                'compare' => 'EXISTS'
            ),
        )
      ) 
    );
    

    … it will get you started but you still need to alter query_orderby because there are hard-coded limits to what you can order by.

    function sort_by_member_number( $vars ) {
      if ( isset( $vars->query_vars['orderby'] ) && 'arcc_member_number' == $vars->query_vars['orderby'] ) {
        $vars->query_orderby = 'ORDER BY arcc_member_number ASC';
      }
      return $vars;
    }
    add_filter( 'pre_user_query', 'sort_by_member_number' );
    

    You are only gong to get users that have the arcc_member_number meta_key with that. If you need all users, just sorted by that key you need still more query manipulation.

Comments are closed.