Skip post in loop and mixin later

In the blog, i try to avoid to show two posts from the same category in succession. So if the latest two posts are from category 1, i want to skip the second one, take post 3 first (if it’s not from category 21 either), and then, mixin the the skiped post before showing number 4.

So what i have is

while (have_posts()) : the_post();

    //get category of post
    $categories = get_the_category();
    $category_id = $categories[0]->cat_ID; 

    //set flag to know, when there was a post form category 1
    if ($flag == true && ($category_id == 1)) {

        //store post to use later
        ....

        continue;
    }

    if ($category_id == 1)
        $flag = true;
    else
        $flag = false;

}

Anyone has an idea?

3 s
3

What about an approach like this:

$first_category_args = array(
    // category id
    'cat'                 => 123,
    // get all from cat
    'posts_per_page'       => -1,
    // don't prepend sticky
    'ignore_sticky_posts' => 1,
    // only return ids
    'fields'              => 'ids'
);
// array of ids
$first_category_query = new WP_Query(
    $first_category_args
);
$first_category_ids = $first_category_query->posts;

$second_category_args = array(
    // category id
    'cat'                 => 456,
    // get all from cat
    'posts_per_page'       => -1,
    // don't prepend sticky
    'ignore_sticky_posts' => 1,
    // only return ids
    'fields'              => 'ids'
);
// array of ids
$second_category_query = new WP_Query(
    $second_category_args
);
$second_category_ids = $second_category_query->posts;

// count    
$first_category_ids_count  = count( $first_category_ids );
$second_category_ids_count = count( $second_category_ids );

// set count to the greater one    
if ( $first_category_ids_count > $second_category_ids_count ) {
    $count = $first_category_ids_count;
} else {
    $count = $second_category_ids_count;
}

$combined_alternating_category_ids = array();

// create combined alternating array of ids
for ( $c = 0; $c < $count; $c++ ) {
    if ( isset( $first_category_ids[ $c ] ) ) {
        $combined_alternating_category_ids[] = $first_category_ids[ $c ];
    }
    if ( isset( $second_category_ids[ $c ] ) ) {
        $combined_alternating_category_ids[] = $second_category_ids[ $c ];
    }
}

// now do a query with the combined result
$combined_category_args = array(
    // get post by created alternating ids array
    'post__in' => $combined_alternating_category_ids,
    // we're ordering by the order the ids have in the array
    'orderby'  => 'post__in'
);
$combined_query = new WP_Query(
    $combined_category_args
);

// proceed with a loop
if ( $combined_query->have_posts() ) {
    while ( $combined_query->have_posts() ) {
        $combined_query->the_post();
        // show post code
    }
} else {
    // no post code
}

wp_reset_postdata();

Just as an idea, haven’t tested this, gave it a quick test, does work as expected.


To alter the main query you can do:

function wpse163419_alternate_order_array() {
    $first_category_args = array(
        // category id
        'cat'                 => 1,
        // get all from cat
        'posts_per_page'       => -1,
        // only return ids
        'fields'              => 'ids'
    );
    // array of ids
    $first_category_query = new WP_Query(
        $first_category_args
    );
    $first_category_ids = $first_category_query->posts;

    $second_category_args = array(
        // category id
        'cat'                 => 3,
        // get all from cat
        'posts_per_page'       => -1,
        // only return ids
        'fields'              => 'ids'
    );
    // array of ids
    $second_category_query = new WP_Query(
        $second_category_args
    );
    $second_category_ids = $second_category_query->posts;

    // count    
    $first_category_ids_count  = count( $first_category_ids );
    $second_category_ids_count = count( $second_category_ids );

    // set count to the greater one    
    if ( $first_category_ids_count > $second_category_ids_count ) {
        $count = $first_category_ids_count;
    } else {
        $count = $second_category_ids_count;
    }

    $combined_alternating_category_ids = array();

    // create combined alternating array of ids
    for ( $c = 0; $c < $count; $c++ ) {
        if ( isset( $first_category_ids[ $c ] ) ) {
            $combined_alternating_category_ids[] = $first_category_ids[ $c ];
        }
        if ( isset( $second_category_ids[ $c ] ) ) {
            $combined_alternating_category_ids[] = $second_category_ids[ $c ];
        }
    }

    return $combined_alternating_category_ids;
}

add_action( 'pre_get_posts', 'wpse163419_cat_alternate_order' );
function wpse163419_cat_alternate_order( $query ) {
    // avoid infinite loop
    remove_action( 'pre_get_posts', __FUNCTION__ );
    // get ids
    $combined_alternating_category_ids = wpse163419_alternate_order_array();
    // set query parameter
    if ( ! is_admin() && $query->is_main_query() ) {
        $query->set( 'post__in', $combined_alternating_category_ids );
        $query->set( 'orderby', 'post__in' );
        $query->set( 'posts_per_page', '-1' );
    }
}

Leave a Comment