Friday, August 17, 2012

How to add Multiple Featured Images in WordPress


The post thumbnails feature aka. Featured Image was added to WordPress back in version 2.9 and made it significantly easier for users to associate images with posts or pages. Prior to that we we had to upload an image, copy the url for the image and add that as a custom field if we wanted to do something similar, which is ok when you know how to do it yourself but less than ideal when having to explain the process to clients or other authors. The post thumbnails feature allows you to easily set a single “Featured Image” for a post or page via a separate meta box in the WordPress admin. You simply click on the “Set featured image” link, open up the image dialog, upload or select an image then click the “use as featured image” link.
This works fine for the vast majority of cases but sometimes it would be great to have have more than one image for a post. For example if you have a folio section or a product where you may want to have multiple images. I tried searching for “mulitple post thumbnails”, “multiple featured images” and so on but most of the “solutions” were mainly about looping through all post attachments and displaying these. This can work in some instances but it didn’t provide as much control as I wanted and if you happened to have other images in the post then these would also be displayed.
Eventually I came across a plugin called Multiple Post Thumbnails and decided to tweak that slightly and integrate it directly into my theme instead of using it as a separate plugin. This is how I did it.

Adding support for post thumbnails in your WordPress theme

First things first, before you start adding support for multiple post thumbnails you need to ensure you have the basic post thumbnails enabled for your theme. Check your functions.php file and make sure the following line is present, if not add it in.
1
add_theme_support( 'post-thumbnails' );
You can also define additional sizes for your post thumbnails.
1
2
3
4
5
// Add Custom image sizes
// Note: 'true' enables hard cropping so each image is exactly those dimensions and automatically cropped
add_image_size( 'feature-image', 960, 500, true );
add_image_size( 'medium-thumb', 300, 156, true );
add_image_size( 'small-thumb', 75, 75, true );

Adding the files and support for multiple post thumbnails to your theme

  1. Download the files for the Multiple Post Thumbnails Plugin to your computer
  2. Unzip the files and copy them to a sub-directory in your theme file. There are only two files you will need multi-post-thumbnails.php and multi-post-thumbnails-admin.js. In my case i’ve placed the PHP file in a library sub-directory in my theme and the JavaScript file in a sub-directory called js inside library.
    > theme-name
       > library
         - multi-post-thumbnails.php
         > js
           - multi-post-thumbnails-admin.js
    
  3. Once that’s done you need to make a small tweak to the multi-post-thumbnails.php file.
    From this (line 143)
    1
    2
    3
    public function enqueue_admin_scripts() {
        wp_enqueue_script("featured-image-custom", plugins_url(basename(dirname(__FILE__)) . '/js/multi-post-thumbnails-admin.js'), array('jquery'));
    }
    To this
    1
    2
    3
    4
    public function enqueue_admin_scripts() {
        $template_url = get_bloginfo('template_url') . '/js/multi-post-thumbnails-admin.js';
        wp_enqueue_script("featured-image-custom"$template_url, array('jquery'));
    }
  4. Then go back to your functions.php file and add the following.
    1
    2
    // Load external file to add support for MultiPostThumbnails. Allows you to set more than one "feature image" per post.
    require_once('library/multi-post-thumbnails.php');
    It’s usually a good idea to keep these inclusions at the beginning of your functions.php file so they are included before you try to use any of the functions they add.
  5. You then need to define some additional post thumbnails and specify which post types they should apply to. The default would be ‘post’ but in my case I had created a custom post type called folio where I’d added 4 extra post thumbnails for a total of up to 5 featured image for each folio item. To do this add the following in functions.php just after the add_image_size entries mentioned above.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // Define additional "post thumbnails". Relies on MultiPostThumbnails to work
    if (class_exists('MultiPostThumbnails')) {
        new MultiPostThumbnails(array(
            'label' => '2nd Feature Image',
            'id' => 'feature-image-2',
            'post_type' => 'folio'
            )
        );
        new MultiPostThumbnails(array(
            'label' => '3rd Feature Image',
            'id' => 'feature-image-3',
            'post_type' => 'folio'
            )
        );
        new MultiPostThumbnails(array(
            'label' => '4th Feature Image',
            'id' => 'feature-image-4',
            'post_type' => 'folio'
            )
        );
        new MultiPostThumbnails(array(
            'label' => '5th Feature Image',
            'id' => 'feature-image-5',
            'post_type' => 'folio'
            )
        );     
     
    };
That’s it, you’ve now added support for mulitple post thumbnails for your post or custom post type and you should see several “Featured Images” boxes in your admin screen. This is what mine looked like.


Displaying the post thumbnails in your WordPress posts

So now you’ve (hopefully) got the admin part working and are able to add multiple post thumbnails to your posts, but you also need to output these in your post or page template. Continuing on my folio concept I wanted to output these images to use in a JavaScript slider. I happened to be using the Nivo Slider at the time but it doesn’t really matter what you use, you’ll just need to tweak the HTML output to match what your slider expects.
This is where the added control of the featured images comes in handy over just scanning through attachments, you might find it easier just to upload a bunch of images and let WordPress use all of the attachments but I needed control over the order and also wanted the freedom to add more images into the description of a folio item without having to worry about it ending up in the slider.
Here’s the PHP code. I’ll try to explain a bit more how it works. The listing is done in two steps. First we show the standard featured image, we then loop through and display all the extra featured images. Because I wanted to use the Nivo slider thumbnail view I had to include a REL attribute with the url for the thumbnail version of the image. After a lot of searching I finally figured that I could add an array of attributes when calling the_post_thumbnail() and this also worked for wp_get_attachment_image() which I ended up having to use instead of the standard MultiPostThumbnails::the_post_thumbnail().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id="slider">         
    <?php   
        // Checks if post has a feature image, grabs the feature-image and outputs that along with thumbnail SRC as a REL attribute
        if (has_post_thumbnail()) { // checks if post has a featured image and then outputs it.    
            $image_id = get_post_thumbnail_id ($post->ID ); 
            $image_thumb_url = wp_get_attachment_image_src( $image_id,'small-thumb');                              
            $attr = array(
                'class' => "folio-sample",                                  
                'rel' => $image_thumb_url[0], // REL attribute is used to show thumbnails in the Nivo slider, can be skipped if you don't want thumbs or using other slider
            );
            the_post_thumbnail ('feature-image', $attr);                                           
        }
        if (class_exists('MultiPostThumbnails')) {                             
        // Loops through each feature image and grabs thumbnail URL
        $i=1;
            while ($i<=5) {
                $image_name = 'feature-image-'.$i// sets image name as feature-image-1, feature-image-2 etc.
                if (MultiPostThumbnails::has_post_thumbnail('folio', $image_name)) {
                    $image_id = MultiPostThumbnails::get_post_thumbnail_id( 'folio', $image_name, $post->ID );  // use the MultiPostThumbnails to get the image ID
                    $image_thumb_url = wp_get_attachment_image_src( $image_id,'small-thumb');  // define thumb src based on image ID
                    $image_feature_url = wp_get_attachment_image_src( $image_id,'feature-image' ); // define full size src based on image ID
                    $attr = array(
                        'class' => "folio-sample",      // set custom class
                        'rel' => $image_thumb_url[0],   // sets the url for the image thumbnails size
                        'src' => $image_feature_url[0], // sets the url for the full image size
                    );                                                                                     
                    // Use wp_get_attachment_image instead of standard MultiPostThumbnails to be able to tweak attributes
                    $image = wp_get_attachment_image( $image_id, 'feature-image', false, $attr );                    
                    echo $image;
                }                          
                $i++;
            }                           
         
        }; // end if MultiPostThumbnails
     ?>
</div><!-- end #slider -->
Now all of this can be done a lot easier just using the standard call from the plugin e.g.
1
2
3
4
5
6
7
8
9
10
11
if (class_exists('MultiPostThumbnails') {
    if (MultiPostThumbnails::has_post_thumbnail('folio', 'feature-image-2')) {
        MultiPostThumbnails::the_post_thumbnail('folio', 'feature-image-2');
    }
    if (MultiPostThumbnails::has_post_thumbnail('folio', 'feature-image-3')) {
        MultiPostThumbnails::the_post_thumbnail('folio', 'feature-image-3');
    }
    if (MultiPostThumbnails::has_post_thumbnail('folio', 'feature-image-3')) {
        MultiPostThumbnails::the_post_thumbnail('folio', 'feature-image-3');
    }
}
However because I needed the extra control over the output of attributes I ended up having to do it a bit more complex. If you’re planning on using the featured images in a slider that requires specific classes, attributes or HTML structure then you may need to go down the same route I’ve done. Hopefully with the code above most of the hard work will be done for you already.

Final words

Well there you have it, if everything went well you should have a working post with multiple post thumbnails and a more elegant way of adding multiple feature images to your posts. If you’re doing work for clients I think this approach will be a bit more user friendly than trying to explain attachments or pasting in URLs into custom fields. The cool thing is that you can set featured images for completely different uses on the same post as well. They don’t need to be called feature images. If you’re doing a real estate web site you could have some images defined as interior, some for exterior and a separate one for floorplan which will give you the control needed to output the right images where needed. It also guides the authors to what they need to add.
Until WordPress 3.3 comes out and hopefully Plupload is integrated into the dashboard this is a pretty decent solution, at least compared to anything else I’ve seen so far.

No comments:

Post a Comment