Use first image of Woocommerce product gallery as posthumbnail
So I have a client who wanted to reuse Woocommerce Product gallery functionality somewhere else on the page, but didn’t needed to set a Featured Image for each individual product.
The culprit
Because the Woocommerce code checks if your product has a post thumbnail set, it won’t display the gallery if that’s empty.
if ( $attachment_ids && $product->get_image_id() ) {
The solution
<?php
class FauxPostThumbnail {
var $faux_product_image_id = false;
public function register_hooks() {
/**
* Use first image in gallery as featured image when it's empty
*/
add_filter('woocommerce_product_get_image_id', [ $this, 'maybe_overwrite_post_thumbnail_if_empty' ] );
// Unset the first image from the gallery image ids array which it stored in $faux_product_image_id
add_filter('woocommerce_product_get_gallery_image_ids', [ $this, 'maybe_unset_first_image_from_gallery' ]);
}
public function maybe_overwrite_post_thumbnail_if_empty( $value ){
// If filled then return original value, because an attachment is selected
if( ! empty( $value ) ) {
return $value;
}
// Else we try to get the first image of the Gallery and return that as our product image
global $product;
$attachment_ids = $product->get_gallery_image_ids();
if( ! empty( $attachment_ids ) ) {
// Because if you would call $product->get_image_id() again, it would crash
$this->faux_product_image_id = $attachment_ids[0];
return $attachment_ids[0];
}
// Return original image
return $value;
}
public function maybe_unset_first_image_from_gallery( $attachment_ids ) {
global $product;
// If we have a filled Gallery and the product doesn't have a featured image, then we know we need to unset the first
if( ! empty( $attachment_ids ) && ! \has_post_thumbnail( $product->get_id() ) ) {
if( $this->faux_product_image_id ) {
// Doesn't work because then the 2nd image becomes the first images and you have a duplicate image again
// array_shift( $attachment_ids );
// This doesn't work, because you get an error that says "cannot unset key 0"
// if (($key = array_search($this->faux_product_image_id, $attachment_ids)) !== false) {
// unset($attachment_ids[$key]);
// }
// So we just loop the aray and don't add the faux_product_image_id to the $new list
foreach( $attachment_ids as $key => $value ){
if( $value !== $this->faux_product_image_id ) {
$new[] = $value;
}
}
return $new;
}
}
return $attachment_ids;
}
}
Fallback image for product
This is also a nice way of having a more relevant fallback image for your product, instead of the default Woocommerce fallback image.