Find All Products without An Image in WooCommerce

Just paste the following at the bottom of your functions.php file. It will print an array of products without images to a file called no_woo_images.log in your theme’s root directory.

// ********* Get all products and variations and sort alphbetically, return in array (title, sku, id)*******
function get_woocommerce_product_list() {
    $full_product_list = array();
    $loop = new WP_Query( array( 'post_type' => array('product'), 'posts_per_page' => -1 ) );
    while ( $loop->have_posts() ) : $loop->the_post();

        $theid = get_the_ID();
        $product = new WC_Product($theid);

        if (!has_post_thumbnail($theid)) {
            $sku = get_post_meta($theid, '_sku', true );
            $thetitle = get_the_title();
            // add product to array but don't add the parent of product variations
            if (!empty($sku)) {
                $full_product_list[] = array(
                    'Title' => $thetitle, 
                    'SKU/Item #' => $sku, 
                    'Item ID' => $theid

    endwhile; wp_reset_query();
    // sort into alphabetical order, by title

    $no_match_file = get_stylesheet_directory();
    $no_match_file .= '/no_woo_image.log';
    file_put_contents($no_match_file, print_r($full_product_list, true));

Attach Images to Products with the Same SKU

I found a WordPress code snippet for WooCommerce somewhere on the web and coded a couple changes that might be of some benefit to other developers. The code snippet attaches an image to a product with the exact same SKU. I changed it to find all products with a SKU like the name of the image (which means it can find multiple products) and add the image to it. Or if there’s only one match, it gets the one product and adds the image to it. If there is no match for the image, it writes the name of the image to a file in the theme’s directory.

Also, there is one line of commented, that if uncommented, will get the name of the image and remove anything after a dash. For example, animage-02.jpg becomes animage.

add_action('add_attachment', function( $attachmentID ) {
  if ( ! class_exists( 'WC_Product' ) ) return; // if no WooCommerce do nothing

  //Get the name of the file that was just uploaded
  $src = wp_get_attachment_image_src( $attachmentID, 'full' );
  $filename = pathinfo( $src[0], PATHINFO_FILENAME );

  //OPTIONAL: If you upload an image that has a name like agreatimage-234.jpg, the following line removes everything after the dash, so you just get "agreatimage"
  //$str_name = array_shift(explode('-', $filename));

  //Create the query
  $args = array(
    'post_type' => 'product',
    'meta_key' => '_sku',
    'meta_value' => $filename, //replace this with $str_name to get the functionality of the commented out line
    'meta_compare' => 'LIKE' //find all products with a SKU that is similar to the name of the image

  //Get all the products using the query above
  $prods = get_posts( $args );

  //If no products were found and if there is more than one product
  if ( ! empty($prods) && count($prods) > 1) {
    //Loop through each one
    foreach ($prods as $product) {
        //If it already has a thumbnail, delete it
        if (has_post_thumbnail($product)) {
        // set the new thumbnail for the product
        set_post_thumbnail( $product, $attachmentID );

        //Attach the image to the product(?)
        $attachment = get_post( $attachmentID );
        $attachment->post_parent = $product->ID;
        wp_update_post( $attachment );          
  //If there is only one product
  } else if (! empty($prods) && count($prods) == 1){
    //Take that product out of the array
    $product = array_pop( $prods );
    //Do the same
    if (has_post_thumbnail($product)) {
    set_post_thumbnail( $product, $attachmentID );

    $attachment = get_post( $attachmentID );
    $attachment->post_parent = $product->ID;
    wp_update_post( $attachment );
    //If no products were found, copy the name of the image to a file in the theme so that we know which images did not have a match
    } else {
        $no_match_file = get_stylesheet_directory();
        $no_match_file .= '/no_match_woo.log';
        $no_match = $src[0];
        file_put_contents($no_match_file, print_r($no_match, true), FILE_APPEND);