Skip post in loop and mixin later

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