Modify featured image URL at runtime

HTML generated by the_post_thumbnail() & get_the_post_thumbnail() can be altered using the post_thumbnail_html filter. This works even when there is no post thumbnail. Example:

/**
 * Filters the post thumbnail HTML.
 *
 * @since 2.9.0
 *
 * @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.
 */
function wpse_post_thumbnail_html( $html, $post_id, $post_thumbnail_id, $size, $attr ) {
    // Optionally add any logic here for determining what markup to output.
    // $html will be an empty string if there is no post thumbnail.
    $new_html="<img src="https://placekitten.com/g/600/600" alt="kitten">";
    return $new_html;
}
add_action( 'post_thumbnail_html', 'wpse_post_thumbnail_html', 10, 5 );

The above solution requires that the theme is calling the_post_thumbnail(), but it will work when the post does not have a thumbnail associated with it.

Note that the solution above would not work in the example below if the post does not have a thumbnail. Here, the conditional statement prevents has_post_thumbnail() from being called:

// the_post_thumbnail() will only be called if the post has a thumbnail.
if ( has_post_thumbnail() ) {
    the_post_thumbnail( 'large' );
}

Alternate technique (alters src value for existing featured images)

The wp_get_attachment_image_src filter allows for the src of an attachment to be modified.

This powerful filter affects all attachment image src values, so it is necessary to add/remove the callback function attached to wp_get_attachment_image_src based on the desired conditions.

The begin_fetch_post_thumbnail_html and end_fetch_post_thumbnail_html actions are perfect for this.

Here’s some example code that changes the featured image based on the post id. You can modify this code to use whatever logic is necessary to determine when the wpse_wp_get_attachment_image_src callback should be added and removed.

/**
 * Fires before fetching the post thumbnail HTML.
 *
 * Provides "just in time" filtering of all filters in wp_get_attachment_image().
 *
 * @since 2.9.0
 *
 * @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'.
 */
function wpse_begin_fetch_post_thumbnail_html( $post_id, $post_thumbnail_id, $size ) {
    // For example, if the post id is 1479, we will add our callback to modify the image.
    // You could use whatever logic you need to determine if the filter should be added.
    if ( 1479 === $post_id ) {
        add_filter( 'wp_get_attachment_image_src', 'wpse_wp_get_attachment_image_src', 10, 4 );
    }
} 
add_action( 'begin_fetch_post_thumbnail_html', 'wpse_begin_fetch_post_thumbnail_html', 10, 3 );

/**
 * Fires after fetching the post thumbnail HTML.
 *
 * @since 2.9.0
 *
 * @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'.
 */
function wpse_end_fetch_post_thumbnail_html( $post_id, $post_thumbnail_id, $size ) {
    // Now we remove the callback so that it only affects the desired post.
    if ( 1479 === $post_id ) {
        remove_filter( 'wp_get_attachment_image_src', 'wpse_wp_get_attachment_image_src', 10, 4 );
    }
} 
add_action( 'end_fetch_post_thumbnail_html', 'wpse_end_fetch_post_thumbnail_html', 10, 3 ); 

/**
 * Filters the image src result.
 *
 *
 * @param array|false  $image         Either array with src, width & height, icon src, or false.
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Size of image. Image size or array of width and height values
 *                                    (in that order). Default 'thumbnail'.
 * @param bool         $icon          Whether the image should be treated as an icon. Default false.
 */
function wpse_wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
    $image[0] = 'https://placekitten.com/g/600/600';
    return $image;
}

Leave a Comment