I have set a user metadata named achievements
which is an array containing various numeric values. Using WP_User_Query
, I want to order the list by a specific key within this array named points
.
The following:
$args = array(
'order' => 'DESC',
'orderby' => 'meta_value_num',
'meta_key' => 'achievements',
'number' => $no,
'offset' => $offset
);
…works if achievements
would be a numeric value. How do I alter the $args
array to target the key points
within the metadata key achievements
.
Running a print_r()
of achievements
for a user returns:
Array ( [x1] => 74 [x2] => 383 [x3] => 457 [x4] => 81 [points] => 301 [x5] => 382 [x6] => 12 )
You could save the values with the separate user meta keys:
x1, ..., x6, points
instead of the array:
achievements
to simplify your WP_User_Query()
usage and not having to deal with serialized arrays as user meta values.
But I guess you’ve already considered this setup and wanted to avoid it 😉
A compromise would be to move only the points
out of the achievements
array into a separate meta key.
Update:
When the number of users is relatively small, we can use the following (untested) PHP sorting:
$users2points = array();
$args = array(
'meta_key' => 'achievements',
'number' => $no,
'offset' => $offset
);
$users = get_users( $args );
foreach( (array) $users as $user )
{
$meta = get_user_meta( 'achievements', $user->ID );
if( isset( $meta['points'] )
$users2points[$user->ID] = $meta['points'];
}
asort( $users2points, SORT_NUMERIC );
print_r( $users2points );
Update 2:
Here’s another more adventures PHP sorting that will work directly on the $users
array of WP_User
objects:
$args = array(
'meta_key' => 'achievements',
'number' => $no,
'offset' => $offset
);
$users = get_users( $args );
foreach( (array) $users as $user )
{
$meta = get_user_meta( 'achievements', $user->ID );
// Here we assume the points values are greater or equal to 0:
$user->points = ( isset( $meta['points'] ) ? $meta['points'] : 0;
}
/*
usort( $users, function( $a, $b ) {
return gmp_cmp( $a->points, $b->points );
});
*/
// The gmp_cmp() might suffer from a memory leak,
// according to some PHP bug reports,
// so let's use this instead:
usort( $users, function( $a, $b ) {
if( $a->points === $b->points )
return 0;
else
return ( $a->points > $b->points ) ? 1 : -1;
});
print_r( $users );