5

I am using get_categories to list the child categories of a parent category.

I want to add an image to the child categories, using the get_categories output.

  • I can either take the featured image from any of the posts that are children of the category that I am using get_categories on, IE the grand-child of the parent category. I do not want to show any other grand child information, and would want just one featured image from each set of category children.

The code I currently use is

$args = array('child_of'  => 1  );
$categories = get_categories($args);
  foreach($categories as $category) { 
    echo '<p>Category:'. $category->name.' </p> ';
    echo '<p> Description:'. $category->description . '</p>';
    echo PUT CAT IMAGE HERE;
     } 
  • Or I could add an image to a category using some plugin, and show it in the foreach($categories as $category) output.

But what is the best (and easiest) way to implement this?

7
  • 3
    First you should decide which of those two things you want. Then you could add any code you might already have.
    – kraftner
    Commented Feb 19, 2014 at 17:04
  • Id prefer to take a featured image from a post but if that solution is unwieldy and the other is simple then id want the simpler solution
    – Jon
    Commented Feb 20, 2014 at 6:36
  • Btw, if you're looking for a plugin, there is one called Category Thumbnails that might do the trick for you. Haven't tested it myself, but the usage is pretty much self-explanatory - and described at the plugin repository. Commented Feb 25, 2014 at 15:08
  • but I would need to call it in a get_categories or other such function, and that part is not so clear
    – Jon
    Commented Feb 25, 2014 at 15:10
  • You should decide which of the two you want, else this is not a question, but 3 questions. How do I do X, How do I do Y, and, Should I use X or Y
    – Tom J Nowell
    Commented Mar 1, 2014 at 16:43

4 Answers 4

6
+50

This is possible with a filter on get_terms.

function grab_child_image($terms,$taxonomies,$args) {
  // var_dump($terms,$taxonomies,$args); // debug
  foreach ($terms as &$term) {
    $cp = new WP_Query(
      array (
        'cat' => $term->term_id,
        'fields' => 'ids',
        'ignore_sticky_posts' => true
      )
    );
    // var_dump($cp->posts); // debug
    if ($cp->have_posts()) {
      $attach = new WP_Query(
        array (
          'post_parent__in' => $cp->posts,
          'post_type' => 'attachment',
          'post_status' => 'inherit',
          'ignore_sticky_posts' => true,
          'posts_per_page' => 1
        )
      );
      if ($attach->have_posts()) {
        $term->image = wp_get_attachment_image($attach->posts[0]->ID);
      } else {
        $term->image = 'some other image';
      }
    }
  }
  return $terms;
}
add_filter('get_terms','grab_child_image',10,3);

$args = array('child_of'  => 1  );
$categories = get_categories($args);
foreach($categories as $category) { 
  echo '<p>Category:'. $category->name.' </p> ';
  echo '<p> Description:'. $category->description . '</p>';
  echo $category->image;
} 

remove_filter('get_terms','grab_child_image',10,3);

There are several queries in there, so add that filter only when you need it and remove the filter afterwards.

There are a number of related image functions that you could use instead, if wp_get_attachment_image() doesn't work for your needs, and you can pass a $size parameter to wp_get_attachment_image()-- second parameter-- to get different image sizes. For example replace the line of code with this:

$term->image = wp_get_attachment_image($attach->posts[0]->ID, $size->full);

You can further alter the output of wp_get_attachment_image() by applying a filter to wp_get_attachment_image_attributes-- for example, to add a class as done here.

6
  • works - excellent! 2 Questions. Its pulling thumbnails. How would I change this to the featured image, not thumbnail version? Also how would I add a class to the img tag. Thanks
    – Jon
    Commented Mar 1, 2014 at 18:11
  • @Jon : see the edit.
    – s_ha_dum
    Commented Mar 1, 2014 at 18:30
  • I added the actual working code for the size change as I wasnt sure what to do till I tried a few things.
    – Jon
    Commented Mar 2, 2014 at 11:42
  • Re changing class - When looping you need to take the remove filter out of the function, and put it after the loop, or it only works once.
    – Jon
    Commented Mar 2, 2014 at 12:06
  • remove_filter() is after the foreach loop in my code.
    – s_ha_dum
    Commented Mar 2, 2014 at 13:49
3

Instead of using get_categories(), I'd suggest you take a look at wp_list_categories(). You can get the same output with it, but it has the benefit to be highly customizable.

There are two ways for customization, either via the filter hook wp_list_categories - see in source - or by extending the Walker_Category class - see in source. The latter gives you much more possibilities for customizing, but might be over the top for minor changes. So you have to evaluate what fits your needs best.

Because this topic is actually pretty well covered on WPSE and SO, I'll just give you a short list of references. Besides that you have not given a specific enough description of your needs, it remains a bit vague, although one can know what you want. Anyway, below resources should help you to chose the method fitting for you and additionally should enable you to achieve it.

  1. filter hook wp_list_categories
  2. Walker_Category class

One more remark, personally I would almost always opt for the extending the Walker_Category class method, but for cases where the change you want is very minor. This is of course a bit of personal preference, but has some background, particularly because of re-usability, extendability and - even if it doesn't necessary seem like it - after all it often - maybe even most of the time - is the easier way to achieve the custom output.


Thumbnail from post in child category:

This way you can retrieve your "category thumbnail" from a random post belonging to one of the child categories.

I've commented the code to make it understandable for you how this is done, besides that it should be pretty much self-explanatory.

/**
 * wpse135208_cat_thumb_from_random_child.
 *
 * Get the thumbnail from a random post belonging to one of the child categories.
 *
 * @version 0.1
 *
 * @link https://wordpress.stackexchange.com/q/135208/22534
 *
 * @param integer $c_cat (default: '')
 * @param string/array $size (default: 'post-thumbnail')
 * @param string/array $attr (default: null)
 *
 * @return string
 */
function wpse135208_cat_thumb_from_random_child( $c_cat = '', $size = 'post-thumbnail', $attr = null ) {
    // do nothing if $c_cat is empty
    if( empty($c_cat) ) return;
    // get_terms is used because we only need ids
    $taxonomies = array(
        'category'
        );
    $args = array(
        'child_of' => $c_cat,
        'fields' => 'ids'
        );
    // returns an array of ids
    $child_cats = get_terms( $taxonomies, $args );
    // use this for debugging
    //echo '<pre>'; print_r($child_cats); echo '</pre>';

    $args = array(
        // we use numberposts instead of post_per_page,
        // because if the pre_get_posts filter is used,
        // it can make a difference in this case 
        // we only want one post
        'numberposts' => 1,
        // but we randomize this
        'orderby' => 'rand',
        'category__in' => $child_cats,
        'fields' => 'ids',
        // make sure only posts with featured image are considered
        'meta_query' => array(
            array(
                'key' => '_thumbnail_id',
                'compare' => 'EXISTS'
            )
        )
        );
    // returns an array containing one post id
    $ct_p_id = get_posts( $args );
    // use this for debugging
    //echo '<pre>'; print_r($ct_p_id); echo '</pre>';

    // use this for debugging
    //echo '<pre>'; print_r( ( 1 /*change to 0 to show src info*/ ) ? get_the_post_thumbnail( $ct_p_id[0], $size, $attr ) : wp_get_attachment_image_src( get_post_thumbnail_id( $ct_p_id[0] ) ) ); echo '</pre>'; 
    // now we can use this to return our thumbnail
    return get_the_post_thumbnail( $ct_p_id[0], $size, $attr );
}

Usage like this:

echo wpse135208_cat_thumb_from_random_child( '1', 'thumbnail', null );

In your code use it like shown below:

$categories = get_categories($args);
foreach($categories as $category) { 
    echo wpse135208_cat_thumb_from_random_child($category->cat_ID); 
} 



Category thumbnail via plugin:

This has the benefit of having actual category thumbnails.

I've given the plugin - Category Thumbnails - I mentioned in the comment above a quick test. It's generally working and I feel it's a better solution than what you're proposing in your answer, because it enables you to manage the thumbnails via the wordpress media library.

I discovered a minor bug, the plugin author is notified and replied instantly, so the bug will be fixed soon. If you can't wait you can fix it yourself like this:

However the function

the_category_thumbnail();

doesn't produce a output. it looks like this in the source code of version 1.0.3 :

function the_category_thumbnail($category_id = null, $sizes = array()) {
    print get_the_category_thumbnail($cat, $sizes);
}

I managed to fix the problem like this:

function the_category_thumbnail($category_id = null, $sizes = array()) {
    print get_the_category_thumbnail($category_id, $sizes);
}

So, by making the parameter/argument name equal.

Or you just use get_the_category_thumbnail() instead, you just have to echo it:

echo get_the_category_thumbnail('1');

Another minor disappointment is that the plugin and functions it offers doesn't give you the possibility to work with the generated image sizes. Which isn't that good, because we want the correct size and not always the full size. I'm going to notify the author about that too, so he can improve his plugin further. In the meantime this luckily can easily be fixed by constructing a custom function:

/**
 * wpse135208_cat_thumb_wrapper.
 *
 * Wrapper function to have the ability to use predefined image sizes via wp_get_attachment_image().
 *
 * @version 0.1
 *
 * @link https://wordpress.stackexchange.com/q/135208/22534
 *
 * @param integer $category_id (default: null)
 * @param string/array $size (default: 'thumbnail')
 * @param boolean $icon (default: false)
 * @param string/array (default: null)
 *
 * @return string
 */
function wpse135208_cat_thumb_wrapper( $category_id = null, $size = 'thumbnail', $icon = false, $attr = null ) {
    $category_thumbnail_obj = get_the_category_data( $category_id );
    return wp_get_attachment_image( $category_thumbnail_obj->id, $size, $icon, $attr );
}

Usage like this:

echo wpse135208_cat_thumb_wrapper( '1', 'thumbnail', false, null );

This should help you to get this working. Like I said, it's preferable because you can manage your category thumbnail via the media library. In your code use it like shown below:

$categories = get_categories($args);
foreach($categories as $category) { 
    echo wpse135208_cat_thumb_wrapper($category->cat_ID); 
} 
6
  • I want a loop of a single category with title description & image of subcategories, no post info but can take any picture from any grandchild post for that child category image. I have a working get categories and the for each does the loop. I have seen other posts using get categories with various plugins getting an image. I dont know how they implemented their plugin. But maybe walker function would work better than a plugin for this?
    – Jon
    Commented Feb 23, 2014 at 18:41
  • The "Thumbnail from post in child category" is exactly what I was looking for. Im not in love with my answer but it works, but this is clearly better - but I cant get an output. I tried both echo function( '1', 'thumbnail', null ); & using $category->cat_ID & $category->term_id but nothing
    – Jon
    Commented Mar 1, 2014 at 17:58
  • Yes its showing images now. But it seems to be repeating the same image from a single category, not an image from each category. s_ha_dum 's solution works well. Thanks
    – Jon
    Commented Mar 2, 2014 at 11:29
  • I see, the lesson here, don't do things in a hurry, I had a typo in there. Additionally I changed post_per_page to numberposts, because in this case it is or at least can be beneficial. Besides that, you use whatever answer suits you best. @Jon Commented Mar 2, 2014 at 13:32
  • Thanks for the solution, and I did learn a lot from the function
    – Jon
    Commented Mar 2, 2014 at 13:35
1

Well, I managed to do what I believe you want to do using Advanced Custom Fields, creating a new set of custom fields with one image custom field. From there, set the rules on location to "Taxonomy Term" > "is equal to" > "Categories" (or whatever taxonomy you were using this for).

Once you publish this, it should update where you edit the taxonomies with a new field for an image. Now, it's all a matter of using the ACF function "get_field()" inside your category foreach loop. Here's how you get field from the category.

Example:

<?php foreach ( $categories as $category ) {
    echo get_field('field_name_for_image', $category->taxonomy . "_" . $category->term_id);
} ?>

If you used the default settings for ACF, you should get an array out of this, which is the image object, and for that, read up on Image Field Types from ACF.

It took me <5 minutes to set this up, and the plugin is free. I hope that's quick and easy for you!

Best of luck!

1
  • Ill take a look and see if I can make it work. Thanks
    – Jon
    Commented Feb 25, 2014 at 14:53
0

Wordpress has the code - http://codex.wordpress.org/Function_Reference/get_the_category

     Show Category Images
This outputs category images named after the cat_ID with the alt attribute set to cat_name. You can also use any of the other member variables instead.

<?php 
foreach((get_the_category()) as $category) { 
    echo '<img src="http://example.com/images/' . $category->cat_ID . '.jpg" alt="' . $category->cat_name . '" />'; 
} 
?>

This allows a set up of images inside a get_categories functions. The images have to be setup to match the function. So if $category->name is used, the image must be saved in the right folder with the matching name of the category.

0

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.