Latest TweetsNew version of Disable Gutenberg includes options to disable for specific theme templates and/or post/page IDs. wordpress.org/plugins/disable-…
Perishable Press

Super Loop: Exclude Specific Categories and Display any Number of Posts

[ Image: Detail view of a series of mechanical gears (black and white photo) ] Readers occasionally ask for help with their WordPress loops. Usually, these requests involve modifying the loop with some customized functionality. Frequently, such customization involves one of these popular behaviors:

  • Exclude a specific category
  • Exclude multiple categories
  • Display only one post or excerpt
  • Display some fixed number of posts
  • Play nice with additional loops on the same page

In this article, I present the swiss-army knife of WordPress loops. This highly versatile, “super” loop is standard WordPress code, easily implemented, and fully equipped to handle all of the custom behaviors mentioned above. Further, the PHP employed is self-contained, making it ultra-easy to pimp it up tough with your own (X)HTML markup. This tight little loop is perfect for “latest-post” excerpts, “aside” posts, news/headlines, site updates, urgent messages, and so much more. And since it plays well with multiple loops, the configurational possibilities are simply endless. Ready? Let’s get on with it..

The Complete Code

As is our custom here at Perishable Press, we present the full code offering right up front. Some sites make you wade through fields of copious copy and tedious text before delivering the full-meal deal. Not here. We save the tedious tutorial and long-winded explanations for the proceeding discussion. So, for those of you dropping in for a quick copy/paste fix — here you go:

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

<?php static $count = 0;
if ($count == "n") { break; }
else { ?>

<?php if ( in_category('x') && !is_single() ) continue; ?>
<?php if ( in_category('y') && !is_single() ) continue; ?>
<?php if ( in_category('z') && !is_single() ) continue; ?>

<div class="post">
<?php the_content(); ?>
</div>

<?php $count++; } ?>
<?php endwhile; ?>
<?php endif; ?>

The Breakdown

Now let’s take a look under the hood, one chunk at a time, and translate the loop to meatspeak:

// if everything is in place and ready, let's start the loop

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>



// to display 'n' number of posts, we need to execute the loop 'n' number of times
// so we define a numerical variable called '$count' and set its value to zero
// with each iteration of the loop, the value of '$count' will increase by one
// after the value of '$count' reaches the specified number, the loop will stop
// *USER: change the 'n' to the number of posts that you would like to display

<?php static $count = 0;
if ($count == "n") { break; }
else { ?>



// to exclude all posts from categories 'x', 'y', 'z' unless in single-post view
// create an 'if' statement for each of the three specified categories as follows:
// if the post is in category 'x' and this is not a single-post view, exit the loop
// if the post is in category 'y' and this is not a single-post view, exit the loop
// if the post is in category 'z' and this is not a single-post view, exit the loop
// if no conditions are met, continue the loop; otherwise restart loop with next post
// if none of these conditions are met, run the loop; otherwise restart at the next post
// *USER: change the 'x', 'y', 'z' to the numbers of the categories you want to exclude

<?php if ( in_category('x') && !is_single() ) continue; ?>
<?php if ( in_category('y') && !is_single() ) continue; ?>
<?php if ( in_category('z') && !is_single() ) continue; ?>



// now, if all conditions have been satisfied, the post is displayed
// for CSS styling and layout purposes, we wrap the post content in a div
// we then display the entire post content via the 'the_content()' function
// *USER: change to '<?php the_excerpt(); ?>' to display post excerpts instead

<div class="post">
<?php the_content(); ?>
</div>



// here, we continue with the limiting of the number of displayed posts
// each iteration of the loop increases the value of '$count' by one
// the final two lines complete the loop and close the if statement

<?php $count++; } ?>
<?php endwhile; ?>
<?php endif; ?>

The Throwdown

Using this loop is theoretically simple. First, copy and paste the complete code into your WordPress document. Then, edit each of the three items according to the instructions provided via the “*USER:” comments in the code above. And that should do it. Save, upload, and check it out. If correctly implemented, any non-single page/post view will display only the specified number of posts from categories that have not been excluded. Now let’s look at some cool tweaks that help to customize the loops as desired..

Multiple Views

One of the great things about WordPress code is that there are so many ways to tweak, hack, and bend it to obey your will. As it is currently written, the loop will ignore any/all posts from categories ‘x’, ‘y’, and ‘z’ when not displayed as a single-view post. Thus, for archive views, category views, home views, and every other non-single view for that matter, the loop will not display the posts from the specified categories. Of course, if our “super loop” is used in a location where the excluded posts are not required, such as the home page, then everything is just peaches. However, if the loop is used to view the category archive of one of the excluded categories, no posts will be displayed. To fix this, simply replace each instance of this:

<?php if ( in_category('x') && !is_single() ) continue; ?>

..with one of these:

// use this to display posts from category 'x' in single and archive views only
<?php if ( in_category('x') && !is_single() && !is_archive() ) continue; ?>

// use this to display posts from category 'x' in single and category views only 
<?php if ( in_category('x') && !is_single() && !is_category() ) continue; ?>

// use this to display posts from category 'x' in single, category, and archive views only
<?php if ( in_category('x') && !is_single() && !is_category() && !is_archive() ) continue; ?>

Excerpts Only

Another useful tweak is using this loop as a front-page “Freshest Loaf” type of stunt. To do this, it would be cool to show only a teaser of the full article, an excerpt, if you will. To do this, replace this:

<?php the_content(); ?>

..with this:

<?php the_excerpt(); ?>

No Exclusions

To use the loop without excluding any categories from the displayed posts, simply remove (or comment out) the following lines:

<?php if ( in_category('x') && !is_single() ) continue; ?>
<?php if ( in_category('y') && !is_single() ) continue; ?>
<?php if ( in_category('z') && !is_single() ) continue; ?>

No Restrictions

To use the loop without limiting the number of posts that are displayed, remove (or comment out) each of the following lines:

<?php static $count = 0;
if ($count == "n") { break; }
else { ?>

[ ... ]

<?php $count++; } ?>

The loop will then return the default number of posts, as specified via the WP Admin Options/Reading panel.

Wrap it up..

— Phew! I am like, so totally out of time now. I hope this article has somehow helped the open-source community. Here at Perishable Press, I operate independently — no sponsors, no ads, no gimmicks. I share this information as a way to give back to all the extremely kind and generous free-information peeps out there. Without all of you, I would not be online today. If you benefit from freely available, open-source information, remember to give back to the developers, authors, and designers who have helped reshape the commercial web into something a little more accessible to the rest of us.</soapbox>

Thanks and God bless!

Jeff Starr
About the Author Jeff Starr = Designer. Developer. Producer. Writer. Editor. Etc.
Archives
26 responses
  1. How do you make the bottom of your page where (perishablepress.com):

    2 excerpts of categories showing with multiple categories.

    + a block that lists all the categories with the number of articles on them?

    kindly let me know.

  2. Instead of excluding categories, I would like to utilize this code to display a specific post based on it’s inclusion in multiple categories. How can I modify your code to do so?

    Also, do you know how I can implement category_name=x, where x is the title of the page? I tried using category_name= but that doesn’t seem to work.

    Thanks for your help.

    Gary

  3. Sorry, last comment should have included the php code:

    category_name=<?php the_title(); ?>

  4. Jeff Starr

    Gary,

    Try this for displaying posts belonging to two categories, x and y:

    <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

    <?php static $count = 0;
    if ($count == "n") { break; }
    else { ?>

    <?php if ( in_category('x') && in_category('y') ) { ?>

    <div class="post">
    <?php the_content(); ?>
    </div>

    <?php } ?>
    <?php $count++; } ?>
    <?php endwhile; ?>
    <?php endif; ?>

    And, as for your second question, I guess I am not understanding exactly what you mean. What is it that you are trying to accomplish? Additional information would definitely help..

  5. Thanks for the info, I’ll give that a try. Regarding my second question, I’m using this code to get the slug of the page:

    <?php // Get the page Slug to use later
       $extrapostdata = get_post(the_ID(), ARRAY_A);
       $slug = $extrapostdata['post_name'];
    ?>

    Then I try to use that variable in the following way:

    <?php query_posts('category_name=<?php echo($slug); ?>'); ?>

    ..but I either have the syntax wrong or it just isn’t allowed. I’m hoping the former…any thoughts?

    btw – subscribed to these comments on my original message but did not receive an email when you replied..(?)

    Thanks -Gary

  6. Sorry, the first snippet from comment #6 should be:

    <?php
       $extrapostdata = get_post(the_ID(), ARRAY_A);
       $slug = $extrapostdata['post_name'];
    ?>

  7. Does anybody knows how to show the last comment of a post on a category view that has a loop?

    Thanks

  8. Jeff Starr

    Gary,

    I think it is a matter of syntax..
    Try the following line for query_posts:

    <?php query_posts('category_name='.$slug); ?>

    That is the general syntax for passing variables in WordPress functions.

    Sorry it took so long to get back to you, I work a “regular” offline job from Thursday to Sunday..
    By the way, are the comment-subscription email-notifications working for you?

  9. Cool, that worked – thanks very much!

    The email notification worked on this comment too. what plugin do you use for that?

  10. Jeff Starr

    You are most welcome!

    For the email notifications, I use a plugin called Subscribe to Comments, located here:

    http://txfx.net/code/wordpress/subscribe-to-comments/

  11. I’m still confused. I just want to exclude 1 category from appearing in my RSS feed.

  12. Jeff Starr

    Have you tried something like if(is_feed)?

[ Comments are closed for this post ]