Question

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?

Était-ce utile?

La solution

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à wordpress.stackexchange
scroll top