Skip to content

Instantly share code, notes, and snippets.

@neverything
Last active December 10, 2023 02:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neverything/7118663 to your computer and use it in GitHub Desktop.
Save neverything/7118663 to your computer and use it in GitHub Desktop.
WordPress: pre_get_posts filter to display one post per category. Displays the latest sticky post and therefore excludes the category of the sticky post as we only want one post per category.
<?php
/**
* Main Query for the Front Page
*
* Display the latest post per category. The latest sticky post goes to the
* top. It's category is then excluded as we only want 1 post per category.
*
* @param object $query WP_Query
*/
function sh_pre_get_posts_front_page( $query ) {
// Check that we have the right query
if ( ( $query->is_front_page() || $query->is_home() ) && $query->is_main_query() ) {
// Set up the category ids and post ids arrays
$category_ids = array();
$post_ids = array();
// Get the sticky_posts array
$sticky_posts = get_option( 'sticky_posts' );
// Check if we have sticky posts
if ( is_array( $sticky_posts ) ) {
// Give me the latest first
rsort( $sticky_posts );
// Only 1 sticky post needed
$sticky_post = array_shift( $sticky_posts );
// Get the cateogry of the sticky post
$sticky_post_categories = wp_get_post_categories( $sticky_post );
}
// Set up category args
$category_args = array( 'parent' => 0 );
// Exclude cateogry of the sticky post
if ( isset( $sticky_post_categories ) ) {
$category_args['exclude'] = join( ',', $sticky_post_categories );
}
// Get parent categories
$categories = get_categories( $category_args );
// Get category term_ids
foreach ( $categories as $category ) {
$category_ids[] = $category->term_id;
}
// Get post ID of latest post per category.
foreach ( $category_ids as $category_id ) {
if ( $cat_posts = get_posts( array( 'cat' => $category_id, 'posts_per_page' => 1 ) ) ) {
$first = array_shift( $cat_posts );
$post_ids[] = $first->ID;
}
}
// Add the sticky post to the front of the array
if ( $sticky_post ) {
array_unshift( $post_ids, $sticky_post );
}
// Set the additional query vars in the main Query.
$query->set( 'post__in', $post_ids );
// We handle sticky posts already
$query->set( 'ignore_sticky_posts', 1 );
// Preserver post__in array order
$query->set( 'orderby', 'post__in' );
}
}
add_action( 'pre_get_posts', 'sh_pre_get_posts_front_page' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment