I have a custom post type (speaker) and I would like to load the list of speakers sorted by last name. I can’t seem to figure it out. I tried the code from this post: https://stackoverflow.com/questions/16416217/wordpress-orderby-last-word-in-title

but it didn’t seem to work.

add_action( 'init', 'create_post_type' );
function create_post_type() {
  register_post_type( 'event',
    array(
      'labels' => array(
        'name' => __( 'Conferences' ),
        'singular_name' => __( 'Conference' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'speaker',
    array(
      'labels' => array(
        'name' => __( 'Speakers' ),
        'singular_name' => __( 'Speaker' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'sponsor',
    array(
      'labels' => array(
        'name' => __( 'Sponsors' ),
        'singular_name' => __( 'Sponsor' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'venue',
    array(
      'labels' => array(
        'name' => __( 'Venues' ),
        'singular_name' => __( 'Venue' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'session',
    array(
      'labels' => array(
        'name' => __( 'Sessions' ),
        'singular_name' => __( 'Session' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
}

The code i’m calling the custom post type is:

<?php 
// args  
$args = array(
    'numberposts'   => -1,
    'post_type'     => 'speaker',
    'meta_key'      => 'speaker-front-page',
    'meta_value'    => '1',
    'orderby' => 'speaker_last_name',
    'order'   => 'ASC'
);
// query
add_filter( 'posts_orderby' , 'posts_orderby_lastname' );
$the_query = new WP_Query( $args );
?>
<?php if( $the_query->have_posts() ): ?> <div id="speakerrow"><h1>SPEAKERS<h1><hr>
    <?php while( $the_query->have_posts() ) : $the_query->the_post(); 
echo '<div class="flex_column av_one_third flex_column_div">';
echo do_shortcode("[av_image src="". get_field("speaker-photo')."' attachment="" attachment_size="full" align='center' animation='pop-up' styling='' hover="av-hover-grow" link='".get_the_permalink()."' target="" caption='' font_size="" appearance="" overlay_opacity='0.4' overlay_color="#000000" overlay_text_color="#ffffff"][/av_image]" );
echo do_shortcode("[av_heading tag='h2' padding='10' heading='". get_the_title()."' color="" style="blockquote modern-quote modern-centered" subheading_active="subheading_below" subheading_size="15"]". get_field('speaker-company')."[/av_heading]");
echo '</div>';
?>

the best i could think was to add a custom metafield called last name and am sorting by that, I like not having to type the speakers last name 2 times if possible.

how do i add the order by field to sort by the 2nd (and last) word in the post title?

3 Answers
3

Order by the last word in the post title

To order by the speaker’s last name, you can use the following setup (PHP 5.4+):

// args  
$args = [
    'posts_per_page'   => 10,
    'post_type'        => 'speaker',
    'meta_key'         => 'speaker-front-page',
    'meta_value'       => '1',
    'orderby'          => 'wpse_last_word',          //<-- Our custom ordering!
    'order'            => 'ASC'
];

// query
$the_query = new WP_Query( $args );

where the 'wpse_last_word' input is supported by the following:

/**
 * Order posts by the last word in the post_title. 
 * Activated when orderby is 'wpse_last_word' 
 * @link https://wordpress.stackexchange.com/a/198624/26350
 */
add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
    if( 'wpse_last_word' === $q->get( 'orderby' ) && $get_order =  $q->get( 'order' ) )
    {
        if( in_array( strtoupper( $get_order ), ['ASC', 'DESC'] ) )
        {
            global $wpdb;
            $orderby = " SUBSTRING_INDEX( {$wpdb->posts}.post_title, ' ', -1 ) " . $get_order;
        }
    }
    return $orderby;
}, PHP_INT_MAX, 2 );

This is based on my answer here on ordering terms by the last word.

Leave a Reply

Your email address will not be published. Required fields are marked *