Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I was thinking about a nicer way to display the categories in my sidebar. Instead of a plain list style, I'd like to have images / thumbnails show up as well.

Currently I'm using the following:

<?php wp_list_categories('show_last_updated=1&show_count=1&title_li='); ?> 

Simply displaying the name/link + post count of each category. I want to keep, that but also add a thumbnail to it.

I've been browsing through this board for answers and also thought about how to do it, but I couldn't find a solution yet.

I guess I have to create a function that gets the featured image of the latest post in that category. If a post has more categories, that also shouldn't cause any problems.

Creating a loop with only 1 post in that category and only outputting the thumbnail would be an option, but to set it so that the thumbnail and category match could be a hassle. I'm sure that there must be a better way to do it.

I'm not looking for a plugin (as I'm sure there are some), I want to hardcode it.

If anybody has a good idea or some advice how to approach this, then please help me out.

Thank you very much!

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

You can use a custom Walker, the easiest of which in your case is the Walker_Category and extend it like so:

class CategoryThumbnail_Walker extends Walker_Category {
    // A new element has been stumbled upon and has ended
    function end_el( &$output, $category, $depth, $args ) {
        // Output the standard link ending
        parent::end_el( &$output, $category, $depth, $args );

        // Get one post
        $posts = get_posts( array(
            // ...from this category
            'category' => $category->cat_ID,
            'numberposts' => 1
        ) );
        // If a post has been found
        if ( isset($posts[0]) ) {
            // Get its thumbnail and append it to the output
            $featured = get_the_post_thumbnail( $posts[0]->ID, 'thumbnail', null );
            $output .= $featured;
        }
    }
}

Now your wp_list_categories can utilize that walker by supplying an additional walker argument like so:

wp_list_categories( array('walker' => new CategoryThumbnail_Walker()) );

As you can see we have two additional queries for each category, one to get the latest post, and one to get its featured image, so make sure that this overhead is acknowledged.

If you want to further customize the output you will have to override all of the functionality of end_el or start_el for the Walker_Category class.

Duplicates

To make sure that no duplicate images are shown you have to do the following things:

  • store the displayed image in an array
  • check with every new image whether it exists in the array
  • if it exists - get next post and check its image
  • if it does not exist, add it to array and output
  • understand what you're doing, how it will work and how to turn in into working code in your context (by reading the docs and learning more about PHP and WordPress)

So the code would look something like this:

class CategoryThumbnail_Walker extends Walker_Category {

    // A new element has been stumbled upon and has ended
    function end_el( &$output, $category, $depth, $args ) {
        // Output the standard link ending
        parent::end_el( &$output, $category, $depth, $args );

        // Get one post
        $posts = get_posts( array(
            // ...from this category
            'category' => $category->cat_ID,
            'numberposts' => 10
        ) );

        // we'll record the seen images here
        if ( !isset($this->images_seen) ) $this->images_seen = array();

        foreach ( $posts as $post ) {
            // Get its thumbnail and append it to the output
            $featured = get_the_post_thumbnail( $post->ID, 'thumbnail', null );
            // have we already seen this image?
            if ( in_array($featured, $this->images_seen) ) continue;
            else {
                $this->images_seen []= $featured;
                $output .= $featured;
                break;
            }
        }
    }
}
share|improve this answer
    
Thank you for the code. It doesn't output anything, though. I put the code snippet above into my function.php and changed the function calling to <?php wp_list_categories( array('walker' => new CategoryThumbnail_Walker()) ); ?> The only thing that changed is that there's now a headline saying "Categories" above the category list. –  japanworm Oct 22 '11 at 10:33
    
Do you have posts in your categories? Does the latest one have a featured image? The code above has been tested and works for me. Let's figure out why it doesn't for you. –  soulseekah Oct 22 '11 at 10:42
    
Yes, that was the issue(no thumb).Thanks! If I wanted to style the whole thing a bit, would I have to do that within the function? Like for example I'd like to get rid of the "Categories" title that it's displaying right now, because now it's double. Also, is it possible to write the function so that it will never pick the same image at all? E.g. if one post has 3 categories, then in the list it will display the same image 3 times. Instead it could get the featured image of the post before that recent post in order to avoid a double image. Or is that too complicated? –  japanworm Oct 22 '11 at 10:57
    
Currently it looks like this: i53.tinypic.com/20syfqe.jpg [live] (zoomingjapan.com/blog) –  japanworm Oct 22 '11 at 11:00
    
Please take a look at the wp_list_categories() documentation, esp. at the title_li argument; when you replaced your function call by mine didn't you see that your title_li is removed now? Please read the documentation. To further customize you will have to implement all of the functionality of the Walker_Category class (core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/…) and extend the Walker class instead, that way you'll be able to control the output exactly. –  soulseekah Oct 22 '11 at 11:03
show 17 more comments

I know you said you wanted to not use a plugin, but I am still going to recommend this: Taxonomy Images

You can always just hardcode it into your functions file. It adds a nice little interface to the categories for adding a specific images to each category, and supplies some easy ways to get that image on your pages. It also works on custom taxonomies with no problem.

I mention the plugin because, for a project I was working on I was trying your first approach (to just show the featured image of the latest post in that category) but when a particular post was in more than one category, the same image was repeated multiple times and looked funky.

Having an image for each category kept a consistent look. The plugin is easy to use so the client could change the image with no probleem. I also wrote a little if statement in case the client created a new category but failed to add an image so that it then went on to use the thumbnail of the latest post for that category (sort of long-winded but you get the point):

 <?php
      while ($my_query->have_posts()) : $my_query->the_post(); ?>
        <!--thumbnail -->
<? /*asks if the category has an image...else use the post Thumbnail...then  if not use the wedding.jpg  */ ?>
<span  class="lighten"><a href="<?= add_query_arg('t', strtolower($term->name), home_url( '/videos/' )); ?>">

    <?php 
    $image_link =  "<a href=".home_url( '/' ).(strtolower($term->name)).">";
    $image = apply_filters( 'taxonomy-images-list-the-terms', '', array(
        'taxonomy'     => 'video_types',
        'image_size' => 'detail',
        'after'        => '',
        'after_image'  => '',
        'before'       => '',
        'before_image' => ''
         )
    );


    if ( ! empty( $image ) ) {print $image;}

            elseif ( has_post_thumbnail() ) {the_post_thumbnail(); } 
             else { ?>
    <img src="<?php bloginfo('template_directory'); ?>/images/weddings.jpg" alt="<?php echo $term->name;?>" />
    <?php } ?></a></span><!--#lighten -->
        </div><!--#thumb -->
           <?php
          endwhile;
          ?>
      <?php
        }
      }
    }
    wp_reset_query();  // Restore global post data stomped by the_post().
    ?>
share|improve this answer
    
Thank you very much. I'm sure other people with appreciate your answer and I'll save it for future reference, but for now I'm trying to go without plugins as often as possible :) –  japanworm Oct 22 '11 at 12:05
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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