Fix orphan image attachments in wordpress/woocommerce

I ended up with a load of orphan image attachments. By which i mean the post_parent of the image attachment was 0. This is bad in one particular situation. Although all the images were in use on posts, Google has a habit of indexing the attachment pages as well and often these are not themed and do not contain the info you want end users to see, For example Its possible to use plugins to add no-index no-follow meta tags to the attachment pages that will remove them from search. But this seemed a bit half-arsed. Plugins such as Yoast SEO have options to redirect attachment pages back to the parent post. But this is useless if the post_parent is 0.

So i came up with the following quick hack to run on the server from a ssh prompt.

$sapi_type = php_sapi_name(); 
if (substr($sapi_type, 0, 3) == 'cgi') 
{ die("You are using CGI PHP\n"); } 

require ( ABSPATH . 'wp-admin/includes/image.php' ); 

$args = array( 'posts_per_page' => 1000,
        'offset'           => 0,
        'category'         => '',
        'category_name'    => '',
        'orderby'          => 'date',
        'order'            => 'DESC',
        'include'          => '',
        'exclude'          => '',
        'meta_key'         => '',
        'meta_value'       => '',
        'post_type'        => 'product',
        'post_mime_type'   => '',
        'post_parent'      => '',
        'author'           => '',
        'post_status'      => 'publish',
        'suppress_filters' => true

$posts = get_posts($args);

foreach ($posts as $post) {
   // Get post title
   $post_thumbnail_id = get_post_thumbnail_id( $post->ID );
   $parentid = wp_get_post_parent_id( $post_thumbnail_id );
   if($parentid == 0)
                        'ID' =>  $post_thumbnail_id,
                        'post_parent' =>  $post->ID



This script finds each post of post_type, gets the featured image ID, then looks up this to see if the post_parent is 0. If it is 0 it sets the post_parent of the image to the post ID determined before. The first few lines ensure that this script is only executable from the command line/ssh prompt so that if you leave this on your web-server it cannot be executed by the http process. However i would encourage removing it directly after use.

The things to note with this are:-

  1. This will run on the first 1000 posts, if you need more, probably best to create an outer loop and use that offset parameter
  2. post_type is set to “product” this is good for woocommerce product posts, for regular posts make this “post”

Leave a Reply