0

I have created a custom taxonomy, so I can manually create a list of supporters. That may not be the best way, but it was the only one I knew how to do. Each entry consists of a first and last name, e.g. "John Doe".

Now, I have the following code which creates a list from this custom taxonomy, and sorts it alphabetically using the first letter of the first word:

<?php
    // Get the taxonomy's terms
    $terms = get_terms(
        array(
            'taxonomy'   => 'supporter',
            'hide_empty' => false,
        )
    );
    // Check if any term exists
    if ( ! empty( $terms ) && is_array( $terms ) ) {
        // Run a loop and print them all
        foreach ( $terms as $term ) { ?>
            <li class="supporter-name"><?php echo $term->name; ?></li> <?php
        }
    } 
?>

However, I would like to order the list alphabetically using the first letter of the last word, so I can effectively order it by last name. Is there a way to achieve this that is both stable and performant?

1 Answer 1

0

The trick here is to create an array out of taxonomy's terms and sort it. Before we do the sorting, we need to divide the full name "John Doe" to seperate strings "John" and "Doe". Then we can sort names by last name.

Rest of the instructions and documentations are in the code.

This should work, but I haven't tested this with actual WP terms, so please test it first.

<?php    // Get the taxonomy's terms
$terms = get_terms(
    array(
        'taxonomy'   => 'supporter',
        'hide_empty' => false,
    )
);

// Check if any term exists
if ( ! empty( $terms ) && is_array( $terms ) ) {
    
    // Create a new empty array of supporters ( $supporters ) which will include first and last names.
    $supporters = [];
    foreach ( $terms as $term ) {
        // Divide the whole name to different words.
        // First word ( name_divided[0] ) will be the person's first name
        // Second word ( name_divided[1] ) will be the person's last name
        $name_divided = explode( ' ', trim($term->name) );
        
        // We'll create an array $supporters which has the following structure:
        // $supporters[0] = array (
        //      'firstname' => 'John',
        //      'lastname' =>  'Doe' ),
        // )
        $supporters[] = array( 'firstname' => $name_divided[0], 'lastname' => $name_divided[1] );
    }

    // Here's the magic. Sort the array by last name
    array_multisort (array_column($supporters, 'lastname'), SORT_ASC, $supporters);
    
    // Run a loop and print them all
    foreach ( $supporters as $supporter ) { ?>
        <li class="supporter-name"><?php echo $supporter['lastname'] . ', ' . $supporter['firstname']; ?></li>
        <?php
    }
} ?>

Edit: If the name list consists of names that has 3 or more names, ie. "John of England".

Replace the section

$supporters[] = array( 'firstname' => $name_divided[0], 'lastname' => $name_divided[1] );

With following code:

//Get all other names than last name
        $firstnames = '';
        for ($x = 0; $x < (count($name_divided) - 1); $x++ ) {
            $firstnames .= $name_divided[$x];
            
            // If this is not the last one of first names, add space between names
            if ( $x != (count($name_divided) - 2) )
                $firstnames .= ' ';
        }

        // Use last word (key in array) as last name
        $lastname = array_pop($name_divided);
        
        $supporters[] = array( 'firstname' => $firstnames, 'lastname' => $lastname );

This modification combined to previous code will output "John of England" as

  • England, John of
5
  • 1
    Hi, thanks for the answer and commented code! However, this only works when the name consists of two words. Some names need three or four words, like e.g. "John of England". In this case, your code will only display "John of"... Can you change the code to show the full name and sort by the first letter of the last word instead of first letter of the second word? Commented Jan 27, 2021 at 14:27
  • @JaschaGoltermann I edited my answer. Is this what you are looking for? Commented Jan 27, 2021 at 15:08
  • Thanks for updating the code! Unfortunately, it produces an error: "Warning: count(): Parameter must be an array or an object that implements Countable in /supporter.php on line 72". In my case, line 72 is this one: "for ($x = 0; $x < (count($name_array) - 1); $x++ ) {" Commented Jan 27, 2021 at 15:18
  • I mistakenly used variable $name_array on that added code. Replace it with $name_divided. Also Replace all instances of $name_array. Edit: I corrected the wrong variable in the answer. Commented Jan 27, 2021 at 15:39
  • This works perfectly, thanks for your continued efforts! Commented Jan 27, 2021 at 15:59

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.