Skip to:
Content
Pages
Categories
Search
Top
Bottom

Sorting by last name goes wrong when having multiple words as last name

  • @nielspilon

    Participant

    Hi,

    I’m probably running into a typical Dutch problem here sorting members alphabetically by their last name. I’ve already sorted the members alphabetically with the following code below which is placed into the functions.php file om my child theme.

    function format_last_name_first( $name ) {
        if ( $first_space = strrpos( $name, " ") )
            $name = substr( $name, $first_space + 1 ) . ", " . substr( $name, 0, $first_space );
        return $name;
    }
     
    // BONUS: To make alphabetical sorting the default sorting, use the
    // function below. 
    //
    // In order for this to work properly, <code><option value=&quot;alphabetical&quot;></code>
    // must be the first option for the members-order-select in
    // members/index.php.
     
    function sort_members_alphabetically( $qs = '', $object = false ) {
        if( $object != 'members' ) //for members only
            return $qs;
     
        if ( empty( $qs ) || ! strpos( $qs, "type=" ) ) {
            $args = wp_parse_args($qs);
            $args['type'] = 'alphabetical';
            $args['action'] = 'alphabetical';
     
            $qs = build_query( $args );
        }
     
        return $qs;
    }
    add_action( 'bp_ajax_querystring', 'sort_members_alphabetically', 11, 2 );

    This works fine but only if a member has a single last name like ‘John Doe’. But we Dutch people can have a last name containing multiple words like ‘John de Vries’ where ‘de Vries’ is the last name or even with double last names like ‘John Eelco van Rhooda’ where ‘Eelco van Rhooda’ is the last name.

    Right now these last names are sorted by the last word of the last name like ‘Vries’ instead of ‘de Vries’. So it should be listed under the ‘D’ of ‘de’ instead of the ‘V’ of ‘Vries’ which is happening now.

    Is there a way to solve this?

Viewing 16 replies - 1 through 16 (of 16 total)
  • @shanebp

    Moderator

    You don’t show how you call function format_last_name_first.
    But this approach is probably better:

    // members loop - sort by last name if type== alphabetical
    function alphabetize_by_last_name( $bp_user_query ) {
        if ( 'alphabetical' == $bp_user_query->query_vars['type'] )
            $bp_user_query->uid_clauses['orderby'] = "ORDER BY substring_index(u.display_name, ' ', -1)";
    }
    add_action ( 'bp_pre_user_query', 'alphabetize_by_last_name' );

    As shown, it will do what your function is doing. You will have to change the ‘-1’ variable, probably to ‘1’. More info.

    @nielspilon

    Participant

    Hi Shane,

    Thanks for yourvreply but I already used that snippet. If I try to edit the -1 variable to 1 the members get sorted by their first name.

    Setting it to 0 does nothing and -2 and beyond all sorts the members by their first name.

    @henrywright

    Moderator

    substring_index() doesn’t quite seem to do the job.

    How about something like:

    substr( strstr( 'Robin van Persie', ' ' ), 1 )

    Which would give you van Persie

    @nielspilon

    Participant

    Nope, it returns an error that there are no members to display. I guess that I could replace ‘Robin van Persie’ with something blank like this

    substr( strstr( ' ', ' ' ), 1 )

    Just to clarify, this is the full code in my functions.php to sort the members:

     function alphabetize_by_last_name( $bp_user_query ) {
        if ( 'alphabetical' == $bp_user_query->query_vars['type'] )
            $bp_user_query->uid_clauses['orderby'] = "ORDER BY substring_index(u.display_name, ' ', -1)";
    }
    add_action ( 'bp_pre_user_query', 'alphabetize_by_last_name' );
     
    // To reflect the alphabetical sorting of the member directory, you
    // could also format the names to show the last name first. Here is
    // a helper function to format names as follows: Last, First Middle
    // Etc.
    //
    // To use this function every time a user's name is shown or queried,
    // simply add it as a filter:
    //
    // <code>add_filter ('bp_get_member_name', 'format_last_name_first' );</code>
    //
    // To only reformat the name in the member directory, change your
    // members/members-loop.php file in your (child)theme. Look for
    // <code>bp_member_name()</code>
    // and replace it with
    // <code>echo format_last_name_first ( bp_get_member_name() );</code>
     
    /**
     * Helper function for formatting a name: Last, First Middle Etc.
     *
     * @param string $name
     * @return string Formatted name
    **/
    
    function format_last_name_first( $name ) {
        if ( $first_space = strrpos( $name, " ") )
            $name = substr( $name, $first_space + 1 ) . ", " . substr( $name, 0, $first_space );
        return $name;
    }
     
    // BONUS: To make alphabetical sorting the default sorting, use the
    // function below. 
    //
    // In order for this to work properly, <code><option value=&quot;alphabetical&quot;></code>
    // must be the first option for the members-order-select in
    // members/index.php.
     
    function sort_members_alphabetically( $qs = '', $object = false ) {
        if( $object != 'members' ) //for members only
            return $qs;
     
        if ( empty( $qs ) || ! strpos( $qs, "type=" ) ) {
            $args = wp_parse_args($qs);
            $args['type'] = 'alphabetical';
            $args['action'] = 'alphabetical';
     
            $qs = build_query( $args );
        }
     
        return $qs;
    }
    add_action( 'bp_ajax_querystring', 'sort_members_alphabetically', 11, 2 );

    I guess that members are sorted by the default WordPress first and last name fields right? Just because we’ve added some custom fields to the member profile pages to split their names in first name, ‘surname prefix (it’s for words like ‘van’ ‘de’) and last name. Not all members have a surname prefix though.

    @henrywright

    Moderator

    Did you replace this line:

    $bp_user_query->uid_clauses['orderby'] = "ORDER BY substring_index(u.display_name, ' ', -1)";

    with this:

    $bp_user_query->uid_clauses['orderby'] = "ORDER BY substr( strstr( u.display_name, ' ' ), 1 )";

    ?

    @nielspilon

    Participant

    Yes, only left u.display_name out of it but either way it retuns a ‘Members not found’ message in return.

    @shanebp

    Moderator

    Try this:
    "ORDER BY substring_index( substring_index(u.display_name, ' ', 2), ' ', -1 )";

    @nielspilon

    Participant

    Jackpot! That did the trick, awesome!

    Thanks so much.

    @henrywright

    Moderator

    @shanebp the only problem with substring_index( substring_index( 'Robin van Persie', ' ', 2), ' ', -1 ) is you lose anything after the 2nd delimiter. For example:

    substring_index( 'Robin van Persie', ' ', 2)

    would return Robin van

    and then

    substring_index( 'Robin van', ' ', -1)

    would return van

    So in theory, the order returned could be

    Denis Bergkamp
    Stefan de Vrij
    Barry van Galen
    Robin van Persie
    Ruud van Nistelrooy
    Wesley Sneijder

    As you can see Robin van Persie and Ruud van Nistelrooy are in the wrong order.

    Note though – this will only be a problem if you have many people with words like van or de in their name.

    @shanebp

    Moderator

    Henry – good catch. What’s your solution?

    @nielspilon

    Participant

    Lol, probs for knowing many Dutch soccer players.

    Well actually, the site I’m working on has 127 members and many of them have ‘van’, ‘de’, or ‘van der’ in their last name and the sorting is almost all fine. There are a few mis matches but that’s probably our own fault due to incorrect registration in the WordPress backend.

    It also goes wrong when members have a double first name but I guess that also depends on the registration in the backend. But I still have to check this.

    @henrywright

    Moderator

    @shanebp Maybe just remove the first word from the string? i.e.

    strstr( 'Robin van Persie', ' ' )

    which gives &nbsp;van Persie. Then you just need remove the initial space:

    substr( ' van Persie', 1 )


    @nielspilon
    if the sorting is fine (van, de etc) then that is down to luck 🙂

    @shanebp

    Moderator

    So handle potential secondary and tertiary sorting ? – yikes.

    This can’t be the first time this issue has arisen.
    A deep google should turn up something.

    @henrywright

    Moderator

    why wouldn’t secondary and tertiary sorting be taken care of by substr( strstr( u.display_name, ' ' ), 1 )?

    @nielspilon

    Participant

    Checked in the backend and where it goes wrong is due to our own data entry.

    @henrywright

    Moderator

    @nielspilon I really do think substr( strstr( u.display_name, ' ' ), 1 ) is your answer. You say there’s definitely no members returned with that in place?

Viewing 16 replies - 1 through 16 (of 16 total)
  • The topic ‘Sorting by last name goes wrong when having multiple words as last name’ is closed to new replies.
Skip to toolbar