Jump Menu : Content | Explore | Comments | Search | Home | Sitemap | Contact | Login | Access.

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

[ Keywords: wordpress, loop, have_posts, category, categories, post, posts, asides, excerpts ]

[ 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

Usage

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.

Tweaks

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. Thanks and God bless! </soapbox>

Related articles

About this article

This is article #385, posted by Perishable on Monday, August 06, 2007 @ 04:15pm. Categorized as Function, WordPress, and tagged with loops, php, posts, tips, tricks, WordPress. Updated on March 25, 2008. Visited 22995 times. 27 Responses »

BookmarkSubscribeExplore

« Temporary Site Redirect for Visitors during Site Updates • Up • Local Paper Tarnishes Small Town »


27 Responses

1 • September 10, 2007 at 9:47 am — Anthony says:

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 • September 11, 2007 at 4:26 pm — Gary says:

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 • September 11, 2007 at 4:28 pm — Gary says:

Sorry, last comment should have included the php code:

category_name=<?php the_title(); ?>

4 • September 11, 2007 at 10:10 pm — Perishable says:

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 • September 12, 2007 at 11:04 pm — Gary says:

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 • September 12, 2007 at 11:06 pm — Gary says:

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

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

7 • September 13, 2007 at 8:15 am — Ricardo Contesse says:

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

Thanks

8 • September 16, 2007 at 5:04 pm — Perishable says:

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 • September 18, 2007 at 9:53 am — Gary says:

Cool, that worked - thanks very much!

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

10 • September 18, 2007 at 9:55 am — Perishable says:

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 • October 17, 2007 at 12:57 am — Martin says:

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

12 • October 17, 2007 at 7:57 am — Perishable says:

Have you tried something like if(is_feed)?

13 • November 1, 2007 at 11:30 pm — xaer8 says:

How can i display only current month posts (limited to only maybe 5 posts)?

Thanks in advance.

14 • November 6, 2007 at 6:49 pm — asony says:

Can we exclude search category from search result ?

15 • November 6, 2007 at 6:53 pm — asony says:

I will like to tell in details :

I have 3 category on my blog. I want to put search box on the every category home page. I want to display result for only one category.

Is it possible ?

Thanks.

16 • November 25, 2007 at 3:10 am — Newbee says:

Which file is this code in.

17 • November 25, 2007 at 7:37 am — asony says:

I want to display result on any page.I am currently developing the site, so I can put any where.

18 • November 25, 2007 at 9:21 am — Perishable says:

Newbee,

This code can be used once in just about any .php file available in your WordPress theme. It is intended to be used to loop through posts. For more information, see the WordPress Codex. Thanks :)

19 • November 30, 2007 at 10:50 pm — Arjun says:

Thanks for the nice article.. cleared some doubts!

20 • December 2, 2007 at 11:54 am — Perishable says:

Happy to help, Arjun!

21 • December 2, 2007 at 12:00 pm — Ehab says:

Very nice so far

I want to display Asides.

So first I run a loop to include just asides category and then run the loop again to include just the other categories (or exclude asides here) ?

Can the loop be made to work like this ? Multiple time and include, rather than excluding ?

22 • December 11, 2007 at 12:36 am — unrulyasides says:

good going so far. however, i’ve got a situation where i have a category archive template (say, category-16.php), that, thru the steps listed on this post i created, causes all children of category 16 to inherit the parent category template.

i placed your $count coding into the category-16.php file, and it works perfectly for when i’m viewing the archive for category 16.

however, when i go view the archives for any of the child categories, it doesn’t register the $count function, and reverts back to the default number of posts indicated in the admin options panel.

if you or anyone knew of a workaround for that, appreciation would be bountiful.

23 • December 16, 2007 at 1:26 pm — Colo says:

Thank’s for this tutorial!!!

24 • March 15, 2008 at 9:26 pm — Ryan says:

Brillant! This is so much better than the examples I found in the WordPress codex.

25 • March 24, 2008 at 12:23 pm — ar says:

Thank you for this, I have found other scripts like this but none so simple.

26 • March 25, 2008 at 12:27 pm — Perishable says:

Thanks, everyone, for the positive feedback — it is greatly appreciated. I am glad this tutorial has proven useful! Cheers :)

[ Comments are closed for this post. ]

Trackbacks / Pingbacks

  1. shawn rider dot com » Blog Archive » links for 2008-01-25

Set CSS to lite theme
Set CSS to dark theme