Resorting a WordPress Query Using usort

Resorting a WordPress Query Using usort

Posted by Rainey

WordPress includes some great ways to order your post, page or custom content as it is stored in the database.  But, what if we want to change the content a little bit and then resort it?  Let’s say we have a staff post type where the person’s name is in the post title.  Now, we want to build a directory of employees where they are ordered by last name. We can do something like this with the usort, explode and comparison functions in PHP.

Using the orderby WP Query argument built into WordPress, we can reorder content stored in the database in a variety of ways. In our case, however, are going to grab the last name from the staff post type’s title and resort based on this. For this example, we are going to assume that we have extra fields for placing a person’s suffixes and prefixes into, like Mr., Mrs., Jr., III, etc.

 

PHP’s Explode Function

The first thing we need to do is get the last name of the person.  I am going to use the explode function to do this, which will return our name as an array of strings. The first parameter in this function is used for the delimiter, in this example a space.

So, the example below will create an array for us to store a name in.

 
$name = "First Last";
print_r( explode( ' ', $name ) );

Which will output this:
array
(
[0] => First
[1] => Last
)

Right now I only want the last name, so I can use the end function with the explode function to accomplish this.

$name = "First Last";
echo end(explode( ' ', $name ) );

Which will return “Last.”

PHP’s usort Function

Cool, so now that we can get to the last name for the person, we need to resort all of our names. For this we are going to lean on the usort function. This function used with a little comparison function can be used to step through the last names and reorder them. Here is a quick example of how the function works:

<?php
function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}
?>

Which will output:
0: 1
1: 2
2: 3
3: 5
4: 6

 

Putting it All Together

Okay, using the pieces above it is time to resort our staff members based on last name. While inside the loop to gather our staff I am going to add the following function.  You could also build this into your functions.php page if you need to use it in other places. The comparison function will grab the post_title for each staff member and set things up for the usort, which we will call later.

function personSort( $a, $b ) {
		$aLastName = end( explode( " ", $a->post_title ) );
		$bLastName = end( explode( " ", $b->post_title ) );
		return $aLastName == $bLastName ? 0 : ( $aLastName > $bLastName ) ? 1 : - 1;
	}

 

For the usort portion, we need to get the array that needs to be resorted, which we have set using the WordPress’ get_posts(). Here I have get_posts() set to $term_posts.  The usort function in this case looks like this:

$term_post_args = array(
		'post_type'   => 'staff',
		'numberposts' => '-1',
		'tax_query'   => $tax_query,
		'orderby'     => 'title',
		'order'       => 'DESC'
	);
	$term_posts     = get_posts( $term_post_args );
	usort( $term_posts, 'personSort' ); 
       //usort grabs the $term_posts array and uses the personSort function to determine how to sort them

	//start loop
	foreach ( $term_posts as $post ) : setup_postdata( $post );

 

And, below I have the resorting function setup in a WordPress page template (it does need some formatting).

<?php /*
Template Name: Staff by Directory
*/
?>

<?php get_header(); 

//start loop
if ( have_posts() ) : while ( have_posts() ) : the_post();
	//Staff Resorting Comparison Function
	function personSort( $a, $b ) {
		$aLastName = end( explode( " ", $a->post_title ) );
		$bLastName = end( explode( " ", $b->post_title ) );
		return $aLastName == $bLastName ? 0 : ( $aLastName > $bLastName ) ? 1 : - 1;
	}
	?>

	<header>
		<h1><?php the_title(); ?></h1>
	</header>
	<?php
	$term_post_args = array(
		'post_type'   => 'staff',
		'numberposts' => '-1',
		'tax_query'   => $tax_query,
		'orderby'     => 'title',
		'order'       => 'DESC'
	);
	$term_posts     = get_posts( $term_post_args );
	usort( $term_posts, 'personSort' );

	//start loop
	foreach ( $term_posts as $post ) : setup_postdata( $post );

		//get meta
		$headshot = get_post_meta( $post->ID, "ts_staff_photo", true );
		$title    = get_post_meta( $post->ID, "ts_staff_title", true );
		$phone    = get_post_meta( $post->ID, "ts_staff_phone", true );
		$email    = get_post_meta( $post->ID, "ts_staff_email", true );

		?>

		<div>
			<?php if ( $headshot ) { ?>
				<a href="<?php the_permalink(); ?>"><img src="<?php echo $headshot['src']; ?>" alt="<?php the_title(); ?>" /></a>
				<br>
			<?php } ?>
			<div>
				<?php echo '<h3>' . the_title() . '</h3>' . '<p>' . $title . '<br>' . $phone . '<br>' . $email . '</p>'; //display staff member name and details ?>
			</div>
		</div>

	<?php endforeach;

	wp_reset_query();

endwhile;
endif;

get_footer(); ?>

So, that is the approach I took when I needed to do this. I also want to thank David Cable for helping me understand all of this a little more. Please leave a comment if you have a question, comment or another approach to this problem.

Like what you are reading? Subscribe to receive monthly tips & updates!

A Monthly Roundup of Articles and a Sweet Deal

Get the latest tips, tricks, tutorials and freebies in your inbox once a monthly.

Join our growing community of front-end web developers and designers. We are constantly publishing new industry tips, tricks and tutorials to help you take your game to the next level. We are also going to include a freebie or deal on something cool each month. Enter your email below and you will only receive this email once a month, nothing else.

Subscribe to our mailing list

* indicates required


    Today in Web Design - PHP, Tutorials, WordPress
    Tagged | , , ,

    • jefferymoore83

      Thanks for sharing this Jeff. I had never used usort before but it seems like an extremely useful function.