0

I have a modified theme that displays CPT posts. I am creating a slider that will cycle through all the sticky posts and display them at the top of the page. So far so good.

The problem. When I have less than 5 posts in a given category. The slider code doesn't display posts properly (they shrink in size, repeat, all kinds of weird stuff). Now before you suggest I try a different slider, please note that this one is hardcoded into the theme. I could comment it out, drop in a new code for another slider, but that's just one more plugin/theme element to maintain. I'd like to see if my logic can be fixed.

What I need. I'm looking for an if/else statement that lets me deliver 2 different loops, one where I can pass args of one type, and another to pass the second set of args (which is to pull from all other categories if that specific category has less than 5 posts).

Here is the code I was using - ALMOST SUCCESSFULLY (see below code for more).

<div class="slider">

<ul>
<?php
$term = get_term_by('slug', get_query_var('term'), get_query_var('taxonomy'));
$sticky = get_option('sticky_posts');
    $args_cat_only = array (
        'my_cat' => $term->slug,
        'posts_per_page' => -1,
        'post__in' => $sticky,
        'post_type' => MYCPT_POST_TYPE,
        'post_status' => 'publish',
        'orderby' => 'rand',
    );
$cat_only_query = new WP_Query( $args_cat_only );

if ( $cat_only_query->have_posts() ) {
    while ( $cat_only_query->have_posts() ) {
        $cat_only_query->the_post(); ?>

        <li>
        // items from category only
        </li>

   <?php  } wp_reset_postdata(); 

if( count($cat_only_query->posts) <= 4 ) { 

    $args_all_cats = array ( //Args to pull from all categories
        'orderby' => 'rand',
        'posts_per_page' => -1,
        //'my_cat' => $term->slug,
        'post__in' => $sticky,
        'post_type' => MYCPT_POST_TYPE,
        'post_status' => 'publish'
    );

    $cat_query_all = new WP_Query( $args_all_cats );

    if( $cat_query_all->have_posts() ) {
        while( $cat_query_all->have_posts() ) {
            $cat_query_all->the_post(); ?>

        <li>
        // items from ALL categories
        </li>

   <?php } wp_reset_postdata();
            }
        }
    }
?>    
</ul>

This code works to query all CPT posts, specific to the category we're in, and return sticky posts UNLESS there are less than 5 (4 or less). In that case, it grabs posts from ALL categories. The problem is that because have_posts() returns true ONLY if there ARE posts, my logic is broken when there are ZERO posts from the loop.

I could add yet another elseif/else statement and run through a scenario where there are NO posts, but I'd rather not do that (unless that's the only way). Can I modify my 2nd query somehow, so so that when it does the count check, it says "if there are less than 5, OR there are zero, do foo"?

1 Answer 1

0

I would start by creating an array to put your posts into, to create a counting system of some kind. Dump your list item output into that array, count it, and use the remaining count to call your second query.

<?php
$term = get_term_by('slug', get_query_var('term'), get_query_var('taxonomy'));
$sticky = get_option('sticky_posts');

// Moved the base arguments into one array
$base_args = array( 
    'posts_per_page' => 5,  // Changed to 5, because that's the amount you need
    'post_type' => MYCPT_POST_TYPE,
    'orderby' => 'rand'
    'post__in' => $sticky,
);

// Merge your base arguments and cat only arguments
$args_cat_only = array_merge( $base_args, array (
    'my_cat' => $term->slug,
) );

$cat_only_query = new WP_Query( $args_cat_only );

if ( $cat_only_query->have_posts() ) {
    while ( $cat_only_query->have_posts() ) { $cat_only_query->the_post();
        // Start an Output Buffer
        ob_start();
        ?>

        <li>
        // items from category only
        </li>

        <?php
        // Dump output into list item array
        $list_items[] = ob_get_clean();
    }
    wp_reset_postdata();
}

if ( count( $list_items ) < 5 ) {
     // Find out how many posts you need
     $post_need = 5 - count( $list_items );

     // Change base args posts_per_page to only call the amount of posts you need
     $base_args['posts_per_page'] = $post_need;

     // Run the new query based on base arguments
     $fill_in_query = new WP_Query( $base_args );

    if ( $fill_in_query->have_posts() ) {
        while ( $fill_in_query->have_posts() ) { $fill_in_query->the_post();
            // Start an Output Buffer
            ob_start();
            ?>

            <li>
            // items from category only
            </li>

            <?php
            // Dump output into list item array
            $list_items[] = ob_get_clean();
        }
        wp_reset_postdata();
    }
}
?>

<div class="slider">
<ul>
     <?php echo implode( '', $list_items ); // Print your list items ?>
</ul>
</div>

The only problem now is that your random pull in your second query could technically pull a random one from the first query.

I didn't test any of this code, please let me know if you have any questions.

5
  • Thank you, that seems to be working! I don't care if it pulls a random one from the first query. The only issue is that I need to be able to output MORE than 5. Sometimes the category will have 100+ posts. I want to cycle thru them all. When changing base args to "5" posts_per_page, it limits the whole thing. Commented Oct 28, 2016 at 15:49
  • Also, I should mention, the LI output would be exactly the same. It's the args that change. Commented Oct 28, 2016 at 15:50
  • That's why you usually limit your posts_per_page to be the amount you need. It's a massive server hit when you request -1 of all 100+ posts.
    – socki03
    Commented Oct 28, 2016 at 16:16
  • And I'd figured the output was the same, there's probably a way to clean that up as well.
    – socki03
    Commented Oct 28, 2016 at 16:18
  • I could probably do like 20-25 of them. In reality, I don't know how long someone will be on the page to watch them scroll by. But at 5, it's clear as the fifth one cycles back round you're watching the exact same posts go by. Commented Oct 28, 2016 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.