I am looking for something very similar to this question. However, the answer provided there seems strange to me. I don't know what the arguments posts_per_page=-1 and it seems more like a hack to me than an actual solution.

I tried the following, which loops the first 6 categories and it works great. However, I want to exclude some categories from this, for instance 1 and 4. I am not entirely sure how to approach this.

<div id="category-posts-content">

    <?php $i = 0; while ($i < 7) : ?>
        <?php query_posts('cat='.$i.'&posts_per_page=3'); ?>
            <?php if ( have_posts() ) : ?>
                <div class="subject">
                    <h3><?php single_cat_title(); ?></h3>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>            
                    <?php endwhile; ?>
            <?php endif; ?>
       <?php $i++; ?>
    <?php endwhile; ?>
    <?php wp_reset_query(); ?>

NOTE: some posts belong into more than one category!

  • Is this a custom template or category.php? Also, you shold never really use query_posts() - create your own custom query using the WP_Query class.
    – David Gard
    Commented Feb 11, 2015 at 11:43
  • @DavidGard This snippet will eventually be output inside single.php. Thanks for the tip! Commented Feb 11, 2015 at 12:06
  • @DavidGard never really use is wrong and not strong, it should be never use, period. :-) Commented Feb 11, 2015 at 12:08
  • @PieterGoosen - I'll make sure I make the statment IN CAPS AND BOLD next time :)
    – David Gard
    Commented Feb 11, 2015 at 12:11
  • 1
    :-) Already busy writing up an essay. Halfway done :-) Commented Feb 11, 2015 at 12:28

1 Answer 1


posts_per_page=-1 is perfectly fine. This is used to get all posts. As for your code, you should never ever use query_posts unless you want to intensionally break stuff on your pages. This is one of the most common functions used and yet the one function that causes the most problems in a website.

I have recently done a post on custom queries and have included many important links to important posts that you have to read, including why you should never use query_posts. You have stated in your previous question that you need to learn a lot, well, this post and the linked ones should be a great learning curve :-). Please check it out here.

What I find extremely odd about your code is that you are using a counter for category ID's. This is really unpredictable, because all tags, categories and custom taxonomy terms and post formats share the same tables, so the ID's are not sequential for a given taxonomy. You should rather make use of get_categories() to gt an array of all the categories. More reliable, and you have the exclude parameter to exclude categories and the include parameter if you only need specific categories

You will need to run a separate query for every category. This can be quite resource intensive, so you might want to look at putting the results in a transient (check this post) or a cache.

You can try something in the line of this:

$categories = get_categories(array('exclude' => '4, 7'));

foreach ($categories as $category) {

    $args = array(
        'cat' => $category->cat_ID,
        'posts_per_page' => 3
    $q = new WP_Query($args);
    while($q->have_posts()) {

        //your template tags and HTML mark up




Just a last note, something that I have initially missed, you only do one while() loop, not two as in your question :-)

  • Sorry, but I one slight change in my code, the_post() should be $q->the_post() Commented Feb 11, 2015 at 13:22
  • After fiddling around I got it to work! Question though, why is wp_reset_postdata(); inside the foreach loop? Or, more precisely, does it matter whether it is inside foreach or out? Commented Feb 11, 2015 at 15:59
  • I like to reset every query, say you have 4 categories, that means 4 queries. To avoid that one query might influence the next, I reset every one, that is why my wp_reset_postdata() is inside the loop. I caught your comment before you edited it :-), you can use echo $category->name just before your loop to display the category name Commented Feb 11, 2015 at 16:11
  • Ah, I see. Haha, darn it. Figured it out moments after I posted that comment and didn't want to come on as stupid or lazy, so I edited that part out. Too late I guess. Thanks again, works great! Commented Feb 11, 2015 at 16:15
  • One is never stupid, just eager to learn. :-) Glad it worked out for you Commented Feb 11, 2015 at 16:21

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.