Tldr;
Modify the_post_thumbnail() function to allow for parameters to be added to the end of the image URL.
Details
By default the_post_thumbnail() accepts two parameters:
1. Size (string|array)
2. Attributes (string|array)
(https://developer.wordpress.org/reference/functions/the_post_thumbnail/)
I need a third one:
3. Parameters (string|array)
The parameters would be appended to the end of the image URL, just like this example:
https://demo.gumlet.com/lemon.jpeg?mode=fill&fill=solid&width=500&height=500&fill-color=c0c0c0&format=auto
Practical example:
This function:
the_post_thumbnail_extended(
array(
'mode' => 'fill',
'fill' => 'solid',
'w' => '300',
'h' => '200',
),
array(
300,
200
),
array(
'class' => 'my-image'
),
);
Would output:
<img src="https://www.example.com/wp-content/uploads/post-thumbnail.jpg?mode=fill&fill=solid&w=300&h=200" class="my-image wp-post-image" alt="alt text" width="300" height="200">
John Cotton answers:
You can modify the image src using a filter:
function filter_image_attributes( $attr, $attachment, $size ) {
$attr['src'] .= '?mode=fill&fill=solid&w=300&h=200';
return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', 'filter_image_attributes', 10, 3 );
Since you're also getting the attachment details (a WP Post) and the size (eg 'post-thumbnail'), you could put conditions in there to act how/when you need.
If you only need this one-off, consider an in-line function immediately prior to the the_post_thumbnail() call, like this:
$params = ['mode' => 'mode', 'fill' => 'solid', 'w' => 300, 'h' => 200];
add_filter( 'wp_get_attachment_image_attributes', function ( $attr, $attachment, $size ) use ( $params ) {
$attr['src'] .= sprintf( '?mode=%s&fill=%s&w=%d&h=%d', $params['mode'], $params['fill'], $params['w'], $params['h'] );
return $attr;
}, 10, 3 );
the_post_thumbnail();
moonshotmedia comments:
Thank you, this is great, I didn't know this option existed.
The only issue is that when I use this function with a conditional, all other featured images that don't meet the condition are now missing the src-attribute.
Code:
function filter_image_attributes( $attr, $attachment, $size ) {
if ( is_post_type_archive( 'my_post_type' ) ) {
$attr['src'] .= '?w=300&h=200&mode=crop&crop=smart';
return $attr;
}
}
add_filter( 'wp_get_attachment_image_attributes', 'filter_image_attributes', 10, 3 );
The images on the post-type archive page now show the correct markup, including the "src" with attributes.
However on all other posts/pages/archives the image "src" is now missing, so no featured images are displayed.
Do you have an idea what could be happening?
John Cotton comments:
You need to return $attr regardless of whether you change it or not (that's how filters work in WP).
So:
function filter_image_attributes( $attr, $attachment, $size ) {
if ( is_post_type_archive( 'my_post_type' ) ) {
$attr['src'] .= '?w=300&h=200&mode=crop&crop=smart';
}
// Outside the if statement
return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', 'filter_image_attributes', 10, 3 );
Arnav Joy answers:
or you can use following all functions.
function the_post_thumbnail_extended( $aj_args, $size = 'post-thumbnail', $attr = '' ) {
echo get_the_post_thumbnail_extended( $aj_args, null, $size, $attr );
}
function get_the_post_thumbnail_extended( $aj_args, $post = null, $size = 'post-thumbnail', $attr = '' ) {
$post = get_post( $post );
if ( ! $post ) {
return '';
}
$post_thumbnail_id = get_post_thumbnail_id( $post );
$size = apply_filters( 'post_thumbnail_size', $size, $post->ID );
if ( $post_thumbnail_id ) {
do_action( 'begin_fetch_post_thumbnail_html', $post->ID, $post_thumbnail_id, $size );
if ( in_the_loop() ) {
update_post_thumbnail_cache();
}
$html = wp_get_attachment_image_extended( $aj_args, $post_thumbnail_id, $size, false, $attr );
do_action( 'end_fetch_post_thumbnail_html', $post->ID, $post_thumbnail_id, $size );
} else {
$html = '';
}
return apply_filters( 'post_thumbnail_html', $html, $post->ID, $post_thumbnail_id, $size, $attr );
}
function wp_get_attachment_image_extended( $aj_args, $attachment_id, $size = 'thumbnail', $icon = false, $attr = '' ) {
$html = '';
$image = wp_get_attachment_image_src( $attachment_id, $size, $icon );
if ( $image ) {
list( $src, $width, $height ) = $image;
$hwstring = image_hwstring( $width, $height );
$size_class = $size;
if ( is_array( $size_class ) ) {
$size_class = join( 'x', $size_class );
}
$attachment = get_post( $attachment_id );
$src = $src.'?mode='.$aj_args['mode'].'&fill='.$aj_args['fill'].'&w='.$aj_args['w'].'&h='.$aj_args['h'];
$default_attr = array(
'src' => $src,
'class' => "attachment-$size_class size-$size_class",
'alt' => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
);
$attr = wp_parse_args( $attr, $default_attr );
// Generate 'srcset' and 'sizes' if not already present.
if ( empty( $attr['srcset'] ) ) {
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( is_array( $image_meta ) ) {
$size_array = array( absint( $width ), absint( $height ) );
$srcset = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id );
$sizes = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id );
if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) {
$attr['srcset'] = $srcset;
if ( empty( $attr['sizes'] ) ) {
$attr['sizes'] = $sizes;
}
}
}
}
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
$attr = array_map( 'esc_attr', $attr );
$html = rtrim( "<img $hwstring" );
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
}
return $html;
}
Reigel Gallarde answers:
Please try this, it's the same with the_post_thumbnail but added third parameter to accept arrays of attribute for the image src.
function the_post_thumbnail_extended( $size = 'post-thumbnail', $attr = '', $params = array() ) {
$thumbnail = get_the_post_thumbnail( $size, $attr ); // get the thumbnail
if (empty($params)) echo $thumbnail; // return the thumbnail if $params is empty
$thumbnail_src = get_the_post_thumbnail_url( $size ); // get the image url for this thumbnail
$thumbnail_src_new = add_query_arg( $params, $thumbnail_src ); // create a new url by adding $params to the url of the image
echo str_replace($thumbnail_src, $thumbnail_src_new, $thumbnail); // replace the old url with the new one.
}
Reigel Gallarde comments:
Function references:
https://developer.wordpress.org/reference/functions/get_the_post_thumbnail/
https://developer.wordpress.org/reference/functions/get_the_post_thumbnail_url/
https://developer.wordpress.org/reference/functions/add_query_arg/
Monit Jadhav answers:
I tried Arnav's code it works, great job Arnav.
But if the third parameter is left blank you can get these warnings showing on the frontend.
Warning: Illegal string offset 'mode' in
Warning: Illegal string offset 'fill' in
Warning: Illegal string offset 'w' in
Warning: Illegal string offset 'h' in
this happened on line number 48, So Here I suggest a correction that checks if the array is not empty
if(!empty($aj_args)){
if(!empty($aj_args)){
$imgquery = '?';
$counter = 0;
// More flexible way to build the image query
foreach($aj_args as $key=>$value){
$imgquery.=$key;
$imgquery.='=';
$imgquery.=$value;
// Removes the last & sign
if( $counter != count( $aj_args ) - 1) {
$imgquery .= '&';
}
$counter++;
}
print_r($imgquery);
//Old code $src = $src.'?mode='.$aj_args['mode'].'&fill='.$aj_args['fill'].'&w='.$aj_args['w'].'&h='.$aj_args['h'];
$src = $src.$imgquery
}
Also another issue with the solution is that the query was hard coded, so if the third array has more elements they wont render in the query to counter that I did the loop that goes through the third array paramenter and builds a query which then can be added to the image source.
foreach($aj_args as $key=>$value){
$imgquery.=$key;
$imgquery.='=';
$imgquery.=$value;
// Removes the last & sign
if( $counter != count( $aj_args ) - 1) {
$imgquery .= '&';
}
$counter++;
}
print_r($imgquery);
//Old code $src = $src.'?mode='.$aj_args['mode'].'&fill='.$aj_args['fill'].'&w='.$aj_args['w'].'&h='.$aj_args['h'];
$src = $src.$imgquery
Arnav's Code
function wp_get_attachment_image_extended( $aj_args, $attachment_id, $size = 'thumbnail', $icon = false, $attr = '' ) {
$html = '';
$image = wp_get_attachment_image_src( $attachment_id, $size, $icon );
if ( $image ) {
list( $src, $width, $height ) = $image;
$hwstring = image_hwstring( $width, $height );
$size_class = $size;
if ( is_array( $size_class ) ) {
$size_class = join( 'x', $size_class );
}
$attachment = get_post( $attachment_id );
Corrections that remove the offset warnings and also abstracts the third argument and builds the image query
if(!empty($aj_args)){
$imgquery = '?';
$counter = 0;
// More flexible way to build the image query
foreach($aj_args as $key=>$value){
$imgquery.=$key;
$imgquery.='=';
$imgquery.=$value;
// Removes the last & sign
if( $counter != count( $aj_args ) - 1) {
$imgquery .= '&';
}
$counter++;
}
//Arnav's code $src = $src.'?mode='.$aj_args['mode'].'&fill='.$aj_args['fill'].'&w='.$aj_args['w'].'&h='.$aj_args['h'];
// New $src with abstracted $imagequery
$src = $src.$imgquery
}
$default_attr = array(
'src' => $src,
'class' => "attachment-$size_class size-$size_class",
'alt' => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
);
$attr = wp_parse_args( $attr, $default_attr );
// Generate 'srcset' and 'sizes' if not already present.
if ( empty( $attr['srcset'] ) ) {
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( is_array( $image_meta ) ) {
$size_array = array( absint( $width ), absint( $height ) );
$srcset = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id );
$sizes = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id );
if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) {
$attr['srcset'] = $srcset;
if ( empty( $attr['sizes'] ) ) {
$attr['sizes'] = $sizes;
}
}
}
}
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
$attr = array_map( 'esc_attr', $attr );
$html = rtrim( "<img $hwstring" );
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
}
return $html;
}