Whats the Problem?
When using FacetWP to query and display posts, you may find that while you can filter posts based on custom taxonomies, sorting posts by those taxonomies and then by title within each term can be challenging. For instance, if you have a custom taxonomy called ‘partner-tier’ with terms like ‘platinum’, ‘elite’, ‘premier’, and ‘standard’, you might want to sort posts first by these tiers and then by post title alphabetically within each tier. This sorting requirement is crucial for displaying content in a meaningful and organized manner, especially when dealing with hierarchical or categorized content.
The Solution
To address this sorting issue, you need to implement custom sorting logic within the loop that handles the display of posts. The solution involves the following steps:
- Fetch and Store Posts: Collect all the queried posts into an array. This allows you to manipulate and sort the posts before rendering them.
- Custom Sorting Function: Create a custom sorting function using
usort()
to sort posts by the custom taxonomy term first and then by post title. The sorting function needs to handle:- Primary Sort: By the custom taxonomy term using a predefined order.
- Secondary Sort: By the post title alphabetically within each taxonomy term.
- Display Sorted Posts: After sorting, use a loop to output the posts in the desired order.
Below is a code example that demonstrates this approach:
<?php
$custom_order = ['platinum', 'elite', 'premier', 'standard'];
// Array to hold posts
$posts_array = [];
// Collect posts in an array
if (have_posts()) {
while (have_posts()) {
the_post();
$post_id = get_the_ID();
$tier = wp_get_post_terms($post_id, 'partner-tier');
if (is_array($tier) && !is_wp_error($tier) && isset($tier[0])) {
$tier = $tier[0]; // Pass the term object
} else {
$tier = null; // Set to null if no term
}
// Add post to array with tier data
$posts_array[] = [
'post' => $post,
'tier' => $tier
];
}
// Sort posts based on the custom order of tiers and post title
usort($posts_array, function($a, $b) use ($custom_order) {
// Get tier slugs
$slug_a = isset($a['tier']) ? $a['tier']->slug : '';
$slug_b = isset($b['tier']) ? $b['tier']->slug : '';
// Get indices for custom tier order
$index_a = array_search($slug_a, $custom_order);
$index_b = array_search($slug_b, $custom_order);
// Handle cases where tiers are not found in the custom order array
$index_a = ($index_a === false) ? PHP_INT_MAX : $index_a;
$index_b = ($index_b === false) ? PHP_INT_MAX : $index_b;
// First, sort by tier
$tier_comparison = $index_a - $index_b;
if ($tier_comparison !== 0) {
return $tier_comparison;
}
// If tiers are the same, sort by post title
$title_a = get_the_title($a['post']->ID);
$title_b = get_the_title($b['post']->ID);
return strcmp($title_a, $title_b);
});
// Output sorted posts
echo '<div class="resource-container">';
foreach ($posts_array as $item) {
$post = $item['post'];
$tier = $item['tier'];
setup_postdata($post);
// Pass the term object to the template part
get_template_part('template-part/partner', null, array('tier' => $tier));
}
echo '</div>';
// Reset post data
wp_reset_postdata();
} else {
echo '<h1>No Results</h1>';
}
?>