2

I have tried many options but without luck. It should be very simple approach but does not produce results. I am trying to insert default fallback image if there is no featured image in the post. My code that produces the thumbnail:

    <?php if ( has_post_thumbnail() ): ?>
    <div class="post-card__image">
      <a href="<?php the_permalink(); ?>">
        <?php the_post_thumbnail( 'post-card-cropped' ); ?>
      </a>
    </div>
2
  • Do you want to do this by modifying templates or just with filters? Commented Apr 24, 2019 at 9:17
  • This a custom theme that will be released for re-use. I am assuming modifying templates would be smarter way to go? Commented Apr 24, 2019 at 9:35

5 Answers 5

4

Method 1: Set Default Fallback Image for Post Thumbnails Using Plugin

This method is easier and recommended for all users.

First thing you need to do is install and activate the Default Featured Image plugin.

https://wordpress.org/plugins/default-featured-image/

Method 2: Add Fallback Image as Post Thumbnail Manually

Your theme’s images folder is located inside /wp-content/themes/yur-theme/ folder. If it doesn’t have the images folder, then you need to create it.

After you have uploaded the image to your website, the next step is to tell WordPress to look for this image when a post doesn’t have its own post thumbnail.

Your WordPress theme displays post thumbnails in various places. You need to look for the_post_thumbnail() function in theme files. Typically, you’ll find it in archive.php, single.php, or content templates.

Next, you need to add the following code where you want to display post thumbnail.

<?php if ( has_post_thumbnail() ) {
the_post_thumbnail();
} else { ?>
<img src="<?php bloginfo('template_directory'); ?>/images/default-image.jpg" alt="<?php the_title(); ?>" />
<?php } ?>

Don’t forget to replace default-image.jpg with your own image file name.

3

None of the above worked for me. Adding this to my child theme's functions.php causes a default image to be used on the front end for every post that has no featured image set:

function my_filter_thumbnail_id( $thumbnail_id, $post = null ) {
    if ( ! $thumbnail_id ) {
            $thumbnail_id = 289; //id of default featured image
        }
    
        return  $thumbnail_id;
    }
    
 add_filter( 'post_thumbnail_id', 'my_filter_thumbnail_id', 20, 5 );
1
  • I also added if ($post->post_type == 'post') { since it would also display on pages. Commented Feb 4 at 3:20
3

Here is a little more advanced solution. I made this because the featured image guthenburg block puts custom attributes on the image tag. I also wanted to take in account all the other info an uploaded image would have. Like srcset, and full image meta info. This class takes an image in your themes directory, copies it to uploads directory in a "{theme-slug}-defaults" folder and produces all the responsive sizes. Then build the tag just like wordpress would.

It would be rather easy to expand this filter function and put different images for different categories, post types for example. Or create a random generator for an array of default images.

So here it is (put in theme's functions.php):

function my_filter_thumbnail(string $html, int $post_id, int $attachment_id, $size, $attr)
{
    // Shows only for posts and only in list views loops, not in single view
    if(!$attachment_id && get_post_type($post_id) == 'post' && !is_single())
    {
        $default = new DefaultFeaturedImage(
            get_stylesheet_directory() . '/assets/img/default-post-thumbnail.jpg', 
            $size,
            $attr
        );
        $html = $default->generate();
    }

    return $html;

}
add_filter( 'post_thumbnail_html', 'my_filter_thumbnail', 20, 5 );



class DefaultFeaturedImage
{
    private $source, $src, $size, $attr, $image_meta, $width, $height, $folder, $basedir, $path;

    public function __construct($source, $size = 'medium', $attr = []) {
        
        $this->source = $source;
        $this->size = $size;
        $this->attr = $attr;
        $this->folder = get_stylesheet() . '_defaults';

        list( 'basedir' => $this->basedir ) = wp_get_upload_dir();

        $this->path = $this->basedir . '/' . $this->folder; // Uploads path for thumbnail
        $this->src = $this->path . '/' . basename($this->source);
        if ( wp_mkdir_p( $this->path ) ) {
            if ( !file_exists($this->src) ) {
                copy($this->source, $this->src);
            }
        }

        list( $this->width, $this->height ) = getimagesize( $this->src );
        list( $this->width, $this->height ) = image_constrain_size_for_editor( $this->width, $this->height, $this->size );

        $this->generateImageMeta();
        $this->buildAttr();

    }

    /*
    * Largely borrowed from the plugin https://wordpress.org/plugins/regenerate-thumbnails/
    */
    private function getThumbnailSizes() {
        global $_wp_additional_image_sizes;
    
        $thumbnail_sizes = array();
    
        foreach ( get_intermediate_image_sizes() as $size ) {
            $thumbnail_sizes[ $size ]['label'] = $size;
            if ( in_array( $size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
                $thumbnail_sizes[ $size ]['width']  = (int) get_option( $size . '_size_w' );
                $thumbnail_sizes[ $size ]['height'] = (int) get_option( $size . '_size_h' );
                $thumbnail_sizes[ $size ]['crop']   = ( 'thumbnail' == $size ) ? (bool) get_option( 'thumbnail_crop' ) : false;
            } elseif ( ! empty( $_wp_additional_image_sizes ) && ! empty( $_wp_additional_image_sizes[ $size ] ) ) {
                $thumbnail_sizes[ $size ]['width']  = (int) $_wp_additional_image_sizes[ $size ]['width'];
                $thumbnail_sizes[ $size ]['height'] = (int) $_wp_additional_image_sizes[ $size ]['height'];
                $thumbnail_sizes[ $size ]['crop']   = (bool) $_wp_additional_image_sizes[ $size ]['crop'];
            }
        }
    
        return $thumbnail_sizes;
    }

    private function generateImageMeta()
    {
        
        $images = [];
        $editor = wp_get_image_editor( $this->src );
        $generate_new = false;
        foreach ( $this->getThumbnailSizes() as $size )
        {
            $thumb = $this->getThumbnail($editor, $size);
            if ( $thumb ) {
                $images[] = $thumb;
                if ( !file_exists($thumb['file']) )
                    $generate_new = true;
            }
        }
        
        if ( $generate_new )
            $images = $editor->multi_resize($this->getThumbnailSizes());

        $this->image_meta = [
            'width' => $this->width,
            'height' => $this->height,
            'file' => $this->folder . '/' . basename($this->src),
            'filesize' => filesize($this->src),
            'sizes' => $images,
            'image_meta' => null
        ];
            
    }

    /*
    * Largely borrowed from the plugin https://wordpress.org/plugins/regenerate-thumbnails/
    */
    private function getThumbnail( $editor, $size ) 
    {
        
        $dims = image_resize_dimensions( 
            $this->width, 
            $this->height, 
            $size['width'], 
            $size['height'], 
            $size['crop'] 
        );

        if ( ! $dims ) {
            return false;
        }

        list( , , , , $dst_w, $dst_h ) = $dims;

        $suffix   = "{$dst_w}x{$dst_h}";
        $filename = $editor->generate_filename( $suffix );
        $filesize = 0;
        if(file_exists($filename))
            $filesize = filesize($filename);

        return [
            'file' => basename($filename),
            'width'    => $dst_w,
            'height'   => $dst_h,
            'mime-type' => mime_content_type($this->source),
            'filesize' => $filesize,
        ];

    }

    /*
    * Mostly copied from wp_get_attachment_image()
    */
    private function buildAttr()
    {
        
        $size_class = $this->size;

        if ( is_array( $size_class ) ) {
            $size_class = implode( 'x', $size_class );
        }

        $default_attr = array(
            'src'   => $this->src,
            'class' => "attachment-$size_class size-$size_class",
            'alt'   => '',
        );

        $this->attr = wp_parse_args( $this->attr, $default_attr );

        $loading_attr              = $this->attr;
        $loading_attr['width']     = $this->width;
        $loading_attr['height']    = $this->height;
        $loading_optimization_attr = wp_get_loading_optimization_attributes(
            'img',
            $loading_attr,
            current_filter()
        );

        // Add loading optimization attributes if not available.
        $this->attr = array_merge( $this->attr, $loading_optimization_attr );

        // Omit the `decoding` attribute if the value is invalid according to the spec.
        if ( empty( $this->attr['decoding'] ) || ! in_array( $this->attr['decoding'], array( 'async', 'sync', 'auto' ), true ) ) {
            unset( $this->attr['decoding'] );
        }

        /*
            * If the default value of `lazy` for the `loading` attribute is overridden
            * to omit the attribute for this image, ensure it is not included.
            */
        if ( isset( $this->attr['loading'] ) && ! $this->attr['loading'] ) {
            unset( $this->attr['loading'] );
        }

        // If the `fetchpriority` attribute is overridden and set to false or an empty string.
        if ( isset( $this->attr['fetchpriority'] ) && ! $this->attr['fetchpriority'] ) {
            unset( $this->attr['fetchpriority'] );
        }

        // Generate 'srcset' and 'sizes' if not already present.
        if ( empty( $this->attr['srcset'] ) ) {
            
            if ( is_array( $this->image_meta ) ) {
                $size_array = array( absint( $this->width ), absint( $this->height ) );
                $srcset     = wp_calculate_image_srcset( $size_array, $this->src, $this->image_meta );
                $sizes      = wp_calculate_image_sizes( $size_array, $this->src, $this->image_meta );

                if ( $srcset && ( $sizes || ! empty( $this->attr['sizes'] ) ) ) {
                    $this->attr['srcset'] = $srcset;

                    if ( empty( $this->attr['sizes'] ) ) {
                        $this->attr['sizes'] = $sizes;
                    }
                }
            }
        }

        $this->attr = apply_filters( 'wp_get_attachment_image_attributes', $this->attr, null, $this->size );

        $this->attr = array_map( 'esc_attr', $this->attr );

    }

    public function generate()
    {
        
        $hwstring   = image_hwstring( $this->width, $this->height );

        $html = rtrim( "<img $hwstring" );

        foreach ( $this->attr as $name => $value ) {
            $html .= " $name=" . '"' . $value . '"';
        }

        $html .= ' />';

        return $html;

    }
}
2

We can set a default image with the code below.

/**
 * Default post thumbnail image.
 *
 * @param  string $html The Output HTML of the post thumbnail
 * @param  int $post_id The post ID
 * @param  int $post_thumbnail_id The attachment id of the image
 * @param  string $size The size requested or default
 * @param  mixed string/array $attr Query string or array of attributes
 * @return string $html the Output HTML of the post thumbnail
 */
function ns_post_thumbnail_fb( $html, $post_id, $post_thumbnail_id, $size, $attr ) {
 if ( empty( $html ) ) {
    return sprintf(
        '<img src="%s" height="%s" width="%s" />',
        home_url().'/wp-content/uploads/2021/02/hub-logo-dummy.png',
        get_option( 'thumbnail_size_w' ),
        get_option( 'thumbnail_size_h' )
    );
}

return $html;
}
add_filter( 'post_thumbnail_html', 'ns_post_thumbnail_fb', 20, 5 );
1

So you were almost there...

<?php if ( has_post_thumbnail() ) : ?>
<div class="post-card__image">
  <a href="<?php the_permalink(); ?>">
    <?php the_post_thumbnail( 'post-card-cropped' ); ?>
  </a>
</div>
<?php else : ?>
    <!—-... here goes your fallback —->
    <?php echo wp_get_attachment_image( 10, 'post-card-cropped' ); ?>
<?php endif; ?>

In the example above I’m using attachment with ID 10 as default fallback image. But of course you can go further and create an customizable option for this. Or use some static html code/static image... the choice is yours.

1
  • Attachment ID is not perfect solution as we need this working by default. I have tried with static image with answer that Vasim provided, but for some reason none of these add default image. Can you provide you above working example with static image so I can test this one as I have so far tried 5 different code examples and none worked. Very strange. I am adding this in proper place and image path is correct. Thanks! Commented Apr 24, 2019 at 11:28

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.