1

This is probably a typical Dutch issue where you have a last name which can contain multiple words. For example Robin van Persie or Mark de Jong.

Currently I have a list of users ordered by last name, which is the default for get_users. This works fine most of the time but fails when a user has a last name containing more than one word.

For example Mark de Jong is listed between the 'C' and 'E' because of 'de' Jong. However is should be listed between the 'I' and 'K' as Jong should be seen as the word to sort.

Same with Robin van Persie which get listed between the 'U' and 'W' becasue of 'van' Persie. However it should be listed between the 'O' and 'Q' as Persie should be seen as the word to sort.

Is there a way to create a function for this to solve this issue?

Edit: updated with current code:

$allUsers = get_users('orderby=display_name&order=ASC&exclude=1,4');

$users = array();

// Remove subscribers from the list as they won't write any articles

foreach($allUsers as $currentUser)
{
if(!in_array( 'subscriber', $currentUser->roles ))
 {
    $users[] = $currentUser;
 }
}

usort($users, create_function('$a, $b', 'return strnatcasecmp($a->last_name,     
$b->last_name);'));

foreach($users as $user)
{

 // Output 

Thanks in advance!

1
  • Please edit your question to include your relevant code, which will make it easier to give you an answer.
    – Pat J
    Commented Aug 9, 2016 at 13:47

2 Answers 2

2

This should do it:

usort($users, 'wpse_235438_sort_users' );

function wpse_235438_sort_users( $a, $b ) {
    $a_last_name = array_pop( explode( ' ', $a->last_name ) );
    $b_last_name = array_pop( explode( ' ', $b->last_name ) );
    return strnatcasecmp( $a_last_name, $b_last_name );
}

explode() will convert your names into arrays; array_pop() will give you the last item in those arrays, which is what you're looking for. Then you just do the comparison you were already doing to sort them.

Using an anonymous function

Per the PHP page on create_function(), if you're using PHP 5.3 or newer, you should use an anonymous function (or "closure") instead of create_function().

usort($users, function( $a, $b ) {
    $a_last_name = array_pop( explode( ' ', $a->last_name ) );
    $b_last_name = array_pop( explode( ' ', $b->last_name ) );
    return strnatcasecmp( $a_last_name, $b_last_name );
} );
5
  • Tried that but it returns: Warning: usort() expects parameter 2 to be a valid callback, function 'wpse_235438_sort_users' not found or invalid function name. I added the function to my functions.php file.
    – NielsPilon
    Commented Aug 9, 2016 at 14:08
  • Sorry, I meant to say that you need to separate the usort() callback function (ie, function wpse_235438_sort_users( $a, $b )) from the function where you're calling it from. I usually have a section of "helper functions" in my functions.php file, and that's where my usort() callbacks go.
    – Pat J
    Commented Aug 9, 2016 at 14:16
  • ...or you can put the contents of the wpse_235438_sort_users() function into your existing create_function() call.
    – Pat J
    Commented Aug 9, 2016 at 14:18
  • Probably missing a single quote somewhere but this usort($users, create_function( $a_last_name = array_pop( explode( ' ', $a->last_name ) ); $b_last_name = array_pop( explode( ' ', $b->last_name ) ); return strnatcasecmp( $a_last_name, $b_last_name ); )); returns a syntax error, unexpected '', $a->last_name ) )'' (T_CONSTANT_ENCAPSED_STRING)
    – NielsPilon
    Commented Aug 9, 2016 at 14:45
  • I'm guessing that's because create_function() expects a string, not an actual PHP function, as its final parameter. See my edit (using an anonymous function).
    – Pat J
    Commented Aug 9, 2016 at 15:21
0

I am guessing that your real question is "How can I achieve this result?".

I would get all users, stick the values into an array and then sort that array.

$names = array();

foreach($users as $user)
{
$names[] = $user->first_name.' '.$user->last_name;
}

usort($names, function($a, $b) {
    $a = substr(strrchr($a, ' '), 1);
    $b = substr(strrchr($b, ' '), 1);
    return strcmp($a, $b);
});

var_dump($names);
2
  • That code gives an error: Warning: strrchr() expects parameter 1 to be string, object given in
    – NielsPilon
    Commented Aug 9, 2016 at 14:11
  • From the error message you can see that you are passing the wrong kind of data into the strrchr() function. I'll amend my answer.
    – Florian
    Commented Aug 9, 2016 at 14:13

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.