4

How would I change every post so that they had the same, hard-coded featured image?! Say this cigar:

https://www.cigarsofcuba.co.uk/acatalog/slide1.jpeg

(I don't actually want to do this - but it's a stumbling block in something more complex.)

I think it ought to be this:

function set_post_thumbnail( $post, $thumbnail_id ) {
    $thumbnail_id = "https://www.cigarsofcuba.co.uk/acatalog/slide1.jpeg";
    update_post_meta( $post->ID, '_thumbnail_id', $thumbnail_id );

}

add_action( 'save_post', 'set_post_thumbnail' );

... but no cigar. What am I missing? Thanks!

  • Thumbnail id is supposed to be an ID, not a URL - it has to be something that's already in the Media Library. Upload the file to the library, then when you view the attachment details you can see its ID. Set that number as $thumbnail_id. – WebElaine Feb 26 '18 at 19:13
  • Thanks Elaine - useful info to know for the future... It's not solving my current problem though. – JohnG Feb 27 '18 at 9:36
3

Method 1: Using the publish_post hook* and media_sideload_image()

Here we will upload an image from a URL, attach it to the post, and set it as the featured image when the post is published.

*Actually, we're using the dynamic hook {$new_status}_{$post->post_type}, which refers transitioning a post post type to the publish status. See wp-includes/post.php for details.

This example code applies when publishing the post type post. A check is in place so that we do not automatically assign the featured image if one has been manually set. Feel free to customize this as desired.

/**
 * Download image, attach it to the current post, and assign it as featured image
 * upon publishing the post.
 *
 * The dynamic portions of the hook name, `$new_status` and `$post->post_type`,
 * refer to the new post status and post type, respectively.
 *
 * Please note: When this action is hooked using a particular post status (like
 * 'publish', as `publish_{$post->post_type}`), it will fire both when a post is
 * first transitioned to that status from something else, as well as upon
 * subsequent post updates (old and new status are both the same).
 *
 * @param int     $post_id Post ID.
 * @param WP_Post $post    Post object.
 */
add_action( 'publish_post', 'wpse_default_featured_image', 10, 2 );
function wpse_default_featured_image( $post_id, $post ) {
    // Bail if there is already a post thumbnail set.
    $current_post_thumbnail = get_post_thumbnail_id( $post_id );
    if ( '' !== $current_post_thumbnail ) {
        return;
    }

    $url = 'https://www.cigarsofcuba.co.uk/acatalog/slide1.jpeg';
    $title = "The default featured image.";

    $image = media_sideload_image( $url, $post_id, $title, 'id' );
    set_post_thumbnail( $post_id, $image );
}

Method 2: Applying a filter to the post thumbnail.

By using a filter, we can "virtually" set the post thumbnail. This method makes it easier to change the post thumbnail on the fly for all posts.

Filter 1: post_thumbnail_html

The post_thumbnail_html filter can be used to override the HTML output for the post thumbnail:

/**
 * Filters the post thumbnail HTML.
 *
 * @param string       $html              The post thumbnail HTML.
 * @param int          $post_id           The post ID.
 * @param string       $post_thumbnail_id The post thumbnail ID.
 * @param string|array $size              The post thumbnail size. Image size or array of width and height
 *                                        values (in that order). Default 'post-thumbnail'.
 * @param string       $attr              Query string of attributes.
 */
add_filter( 'post_thumbnail_html', 'wpse_post_thumbnail_html', 10, 5 );
function wpse_post_thumbnail_html( $html, $post_id, $post_thumbnail_id, $size, $attr ) {
    return '<img src="https://www.cigarsofcuba.co.uk/acatalog/slide1.jpeg" alt="Have a cigar">';
}

Filter 2: Using get_post_metadata on the _thumbnail_id meta key.

Here's another approach that overrides each post's thumbnail ID with a different ID.

I'd suggest implementing a Customizer setting or options page that allows the special thumbnail image to be uploaded/selected (locally, from a URL, or from the medial library). Then you can use the get_post_metadata filter to modify the value associated with each post thumbnail's meta key _thumbnail_id:

/**
 * Dynamic hook: "get_{$meta_type}_metadata"
 * 
 * Filters whether to retrieve metadata of a specific type.
 * 
 * The dynamic portion of the hook, `$meta_type`, refers to the meta
 * object type (comment, post, or user). Returning a non-null value
 * will effectively short-circuit the function.
 *
 * @param null|array|string $value     The value get_metadata() should return - a single metadata value,
 *                                     or an array of values.
 * @param int               $object_id Object ID.
 * @param string            $meta_key  Meta key.
 * @param bool              $single    Whether to return only the first value of the specified $meta_key.
 */
add_filter( 'get_post_metadata', 'wpse_featured_image_id_override', 100, 4 );
function wpse_featured_image_id_override( $value, $object_id, $meta_key, $single ) {
    $thumbnail_id_key = '_thumbnail_id';

    // Bail if this is not the correct meta key. Return the original value  immediately.
    if ( ! isset( $meta_key ) || $thumbnail_id_key !== $meta_key ) {
        return $value;
    }

    // Add additional guard clauses if necessary... (check post type, etc.)

    // Get the id for an image uploaded elsewhere.
    // This could be pulled from the customizer or a plugin options page.
    return 807;  // Example ID
}
  • Thanks - it's not working though... Should that work if I cut and paste it directly into my functions file, or am I meant to change some of the parameters? – JohnG Feb 27 '18 at 9:43
  • For what it's worth, this code has been tested and is working when outputting the thumbnail using the_post_thumbnail(). Would you please update your question so that it includes the code for displaying the thumbnail on the front end? – Dave Romsey Feb 27 '18 at 10:08
  • I'm possibly oversimplifying. I've no problem getting whatever image I want displaying on the front end of a post - I can just change the single.php file - using set_post_thumbnail() and the_post_thumbnail(). But I want to change the image SAVED to the database as the thumbnail. So I'd think I need to do a save_post action in the functions file? – JohnG Feb 27 '18 at 11:04
  • The advantage of this code is that it does not require modifying the theme's template -- the code can be added from a plugin or child theme for example. If you must upload an image to every post, you might find the code in this gist helpful. – Dave Romsey Feb 27 '18 at 12:54
  • It does seem that uploading the same image to every post would be inefficient and difficult to maintain. If you are going to set the thumbnail when saving the post, the save_post should be ok. I'd suggest creating a Customizer setting or plugin option to select the special image from the media library or URL, then use the get_post_metadata filter to modify the value of _thumbnail_id so that it uses the ID of the special image. – Dave Romsey Feb 27 '18 at 12:55
3

You could simply overwrite the featured image (whether one is set or not) on saving the page / post with this:

//this is called on saving page/post
add_action('save_post', 'force_featured_image');

function force_featured_image( $post_id ){
   //set the featured image
   set_post_thumbnail( $post_id, [image_id] );
}

NOTE Replace '[image_id]' with your image id.

  • Thanks - I've tried this, and similar things... I think my WordPress installation may simply have a bug somewhere, as I can't seem to get it to perform any action with the thumbnail at all. This looks solid to me though. – JohnG Feb 27 '18 at 14:32
  • this code should work, I'm using it on 10's of WP sites. Perhaps try adding a priority value to it, to make it trigger late on, in case another function is getting there after yours. This code should fire only once the post is saved though. So you'll need to save a post before you will see the thumbnail/featured image set to the one you reference in this function. – Phill Healey Feb 27 '18 at 16:21
  • 1
    set_post_thumbnail() takes an attachment id, not a URL. Maybe something is missing here? Also the call to add_action() is shown accepting a method from a class which will probably throw a lot of visitors off. – Dave Romsey Mar 1 '18 at 21:28
  • 1
    @DaveRomsey Fair points. I've edited my answer to simplify. – Phill Healey Mar 2 '18 at 16:42
0
function wpb_autolink_featured_images( $html, $post_id, $post_image_id ) {
    if (! is_singular()) {
        $html = '<a href="' . get_permalink( $post_id ) . '" title="' 
                . esc_attr( get_the_title( $post_id ) ) . '">' . $html . '</a>';
        return $html;
    } else {
        return $html;
    }
}
add_filter( 'post_thumbnail_html', 'wpb_autolink_featured_images', 10, 3 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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