How did we get here?

After a long battle with a very considerate person in the WordPress.org forums where I repeatedly failed to get them working with various attempts at writing code they could drop into their site, I decided I needed to write it up and explain how to do this once and for all.

The scenario:

  • You have a series of posts with Proper Nouns (people’s names) as their title
  • You want to index them on their Family Name (sometimes called Last Name)

The concept is fairly simple, in that you need to hook into the filter that I’ve provided and return the right result with the index altered. This is the rub in my attempt at helping the person on WordPress.org in that I really didn’t understand my own code well enough, despite having written it, so I kept suggesting non-working solutions.

So this is the code that we finally settled upon that worked correctly:

add_filter( 'a_z_listing_item_indices', 'my_a_z_index_filter', 10, 3 );

function my_a_z_index_filter( $indices, $item, $item_type ) {
    // make sure we're filtering the right post type
    if ( 'post-type-we-want' === get_post_type( $item ) ) {
        // pull the title and get the first letter of the second word
        $full_name = explode( ' ', $item->post_title );

        // the last word is in the last element of $title_parts so check it is there
        $last_name = array_pop( $full_name );

        // ensure we actually found a last name
        if ( $last_name )  {
            // cut the first letter out for our index
            $index = substr( $last_name, 0, 1 );

            // set up a new empty array
            $indices = array();

            // only the first names are left in $full_name. Join them together again
            $first_names = join( ' ', $full_name );

            // Now put the last name first and separate with a comma+space from the first names
            $formatted_name = "{$last_name}, {$first_names}";

            // add the new name associated with the item into the new array we created
            $indices[ $index ][] = array(
                'title' => $formatted_name,
                'item' => $item,
            );

            // return a new array with our new index letter instead of the
            // indices already discovered by the plugin
            return $indices;
        }
    }

    // if we get here we didn't override the indices so return
    // those already discovered.
    return $indices;
}