How to list custom taxonomy terms alphabetically by last word

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