Support » Themes and Templates » Display by Category home.php template

  • Along with my plugin work I’ve been spending a bit of time on template experiments, proof of concepts in organizing content differently in WordPress 1.5.

    A method that’s requested often, and one that caught my interest, is to display recent posts organized within their respective categories, instead of just by date (descending). I’ve come up with one solution through a (very) modified post loop in a home.php template, and would like feedback on what I have so far, such as improvements to structure, streamlining code, etc.

    download template | view template | demo

    The modifications to The Loop I’ve made still only handle the last N posts, but it first retrieves the categories they’ve been posted to, and then organizes posts under each. By default categories are organized by latest post first, but uncomment the following line (remove the //) to sort/list the categories alphabetically:

    // uasort($cats, strcasecmp);

    I’ve commented throughout the template, but please ask if something isn’t clear.

    Finally, the template is designed around the default (Kubrick) theme, so it’ll work best with that; however the loop framework can be imported into any layout (with appropriate tweaking).

Viewing 15 replies - 1 through 15 (of 51 total)
  • Oh, this is wonderful!!!! Something I’ve been wanting for ages.

    So this isn’t a plugin but will be a change to the template files? Wow. Very awesome.

    Can you add more than one post to a couple of the demo categories so we can get a better feel for how more than one post would fit under a category?

    And would this display only the most recent posts on the index.php page, leaving out “archived” posts? So if WP is set to display 10 posts chronologically, it would now display 10 posts, chronologically but by category?

    “So this isn’t a plugin but will be a change to the template files? “

    Correct. I looked at how one might incorporate it into a plugin, but got a little lost considering how to go about it. If it can, it would probably need to create a whole new query class to manage overriding The Loop, etc. That appears to be more work than what I put into the template.

    “Can you add more than one post to a couple of the demo categories so we can get a better feel for how more than one post would fit under a category?”


    “And would this display only the most recent posts on the index.php page, leaving out “archived” posts?”

    That’s right. So let’s say you have a blog with 10 categories. If WordPress is set to display 10 posts per page, and the last 10 are in 6 categories, then only 6 categories with be displayed–with those last 10 posts organized chronologically under each of course. (It is also page-aware, so previous/next paging will continue to organize each page of posts in their group of categories.)

    A method could be constructed to display the last N posts for each category (or just select ones), but this would have to nix the built-in Loop functionality entirely.

    Excellent work and easy to integrate into existing styles. One question though – what is the criteria for chosing where a post with two cats goes? Does it go in to the first category listed, or both?

    If a post is in cats 1, 2 and 3, it will be displayed under the category 1 heading. So in other words, it ends up under the first category listed. I focused on ‘posts in a single category’ blogs because they seem to fit the bill for this template, but it wouldn’t be difficult to modify the code so it displays posts under multiple categories.

    This sort of thing would be easier if only WordPress incorporated the concept of a ‘primary’ category…

    So, could this work together with the Top Category plugin – as for ‘primary’?

    moshu, taking a look at how the plugin works, I don’t see why not. Right now my script compares the (first) category of a post with the ‘current’ category to determine the correct one to display it under. The code for that is:

    $category = get_the_category();
    if($current_cat == $category[0]->cat_ID) :

    Using Top Cat’s topcat_get_the_main_category_id() function, this could be changed to:

    $category = topcat_get_the_main_category_id();
    if($current_cat == $category) :

    Or if one needed to test if the ‘top’ category has been set:

    $category = topcat_get_the_main_category_id();
    if(!$category) {
    $category = get_the_category();
    $category = $category[0]->cat_ID;
    if($current_cat == $category) :

    To quote my nephew: “kewl, maaan” 🙂
    My interest at this moment is pure theoretical, but I’ll save this snippet for future use. Thanks!

    Thank you for posting that script it was exactly what I was looking for. Is there way for me to exclude a category from being displayed? I tried a few thing but they didn’t work. I’m not great at this php thing yet. Thanks again.

    (see next post)


    Near the beginning of the template find this block of code:

    /* collect categories */
          foreach($posts as $post) :
             $category = get_the_category();
             $cats[$category[0]->cat_ID] = $category[0]->cat_name;
             $cat_posts[$category[0]->cat_ID] = $post;

    and replace it with this:

    /* collect categories */
          foreach($posts as $post) :
             $category = get_the_category();
             if(10 != $category[0]->cat_ID) {
                $cats[$category[0]->cat_ID] = $category[0]->cat_name;
                $cat_posts[$category[0]->cat_ID] = $post;

    Change 10 in

    if(10 != $category[0]->cat_ID) {

    to the category ID you want to pass over. If you need to exclude more than one category, just before the foreach line in the same block of code, insert this:

    $exclude_cats = array(1, 10, 20);

    Set the array to the category IDs you want to exclude, separating each with a comma. Then change the if line to:

    if(!in_array($category[0]->cat_ID, $exclude_cats)) {

    Actually, the code above will correctly exclude one or more categories, but at the disadvantage of not displaying the correct number of posts per page. I’ll have to look at the template’s code and see what can be done through query_posts or whatnot to solve this.

    I’ve testes your code in the first post
    I’m using the custom query string plugin
    custom query string plugin

    it works!

    is_home show 5 posts per page, ordered by date DESC

    and if I have only 4 categories
    your code shows two posts of the first category

    if I have only 3 categories
    your code shows three posts of the first category

    if I have 5 categories
    your code shows one post per category

    if tested it with
    is_home show 15 posts per page, ordered by date DESC
    and so on

    I’m happy

    and please take a look at this problem

    best regards



    How would you go about removing the category title bar (with the link to the category page) from the posts for a particular category (i.e., your “main” category)?

    Also, how could you specify a maximum number of posts per individual categories…for instance, 5 max per the main category and one each for the rest.



    To selectively remove a category header, locate the <h2> that displays it (right after foreach($cats as $current_cat) in the template), and add just above it an if statement testing the category using a negation of the in_category() function:

    <?php if(!in_category(1)) : ?>

    Change 1 to the numeric category ID of your “main” category, and make sure to close up the if statement after the <h2> element:

    <?php endif; ?>

    Also, how could you specify a maximum number of posts per individual categories

    The “problem” I wanted to solve with this version of home.php was one of organizing the last N posts within their respective categories. For your second issue, you’re asking to manage things far differently.

    Using query_posts(), you could create a custom loop displaying the last 5 posts only within your main category; then (using query_posts() again) initialize the “Display by Category” loop in my template to exclude the main category from the rest. However, this won’t assure only a single post under each of the remaining categories. For that, you’d be better off passing up my template altogether and creating one that provides a custom loop for each category. This way you have full control over where a category is displayed, and how many posts appear in the home page under them.


    Beyond this, it is possible to set maximum posts displayed for each category. Just keep in mind if you want say 10 posts displayed on your main page, you can’t then collect 10 through the normal loop process and set maximum values under a category. The reason for this is, if in the last 10 posts, 7 are in your main category, 2 in a second, and 1 in a third, you’ll have only 7 posts showing (5 in main, and 1 for each of the other categories). If this is acceptable, a count could be set up that tracks the number of posts for each category, and stops displaying posts for a category once it hits its maximum.



    Thank you so much for your prompt reply. I’m partly just a little unsure if I’ll want to have it your way, with only the most recent posts, regardless of category (better for regular visitors), or ensure there’s at least one post from each (better for newbies).

    Would using a separate loop for each category slow down the page load or is the time the database takes to render things virtually inconsequental?



    Now that I’ve done that, it’s only displaying posts from the “main” category. What’s happened?

    <?php if(!in_category(1)) : ?><h2 id=”cat-<?php echo $current_cat; ?>”><?php echo get_the_category_by_id($current_cat); ?></h2><?php endif; ?>

Viewing 15 replies - 1 through 15 (of 51 total)
  • The topic ‘Display by Category home.php template’ is closed to new replies.