wp_list_categories: get latest featured_image of category

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:

Read More
<?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!

Related posts

Leave a Reply

2 comments

  1. 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;
                }
            }
        }
    }
    
  2. 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().
        ?>