There are times when things just go wrong. I had one of those times the other day. The pressure was on to deliver a project, and there were bits of PHP and CSS and JavaScript flying everywhere here at WebAware Central. And so it happened: I wiped the image attachment meta data in the WordPress database.
I’m still not quite sure how I did it, but I think it was a filter hook to a non-existent function in the middle of thumbnail regeneration. WordPress relies on a postmeta field called ‘_wp_attachment_metadata’ for information like the image height and width, and the different thumbnail sizes and filenames. Without it, WordPress isn’t able to serve up thumbnails, or size medium, or any custom image sizes defined by plugins.
Backups! Yes. Great, except we loaded a bunch of new images during the day and the backup was basically the next thing that was going to happen. Too late.
Simply running Regenerate Thumbnails, or my custom bottle size regeneration tool, didn’t work either; they both need the width and height of the full-sized image, and WordPress gets that from… the image attachment meta. The thumbnails themselves are actually regenerated, if you look in the uploads folder; but without the meta, WordPress just doesn’t see them.
So: the fix. It’s surprisingly easy to regenerate image attachment meta from the full-sized images. The process is essentially this:
- get a list of images from WordPress
- get the filename of each image, using get_attached_file()
- get the width and height of each image, using getimagesize()
- create the image attachment meta array for each image
- update in the database
Easy. I just hooked up the code below to an admin menu item, and ran it. Bob is, apparently, a close relation on my mother’s side. And then, Regenerate Thumbnails fixed all the thumbnail sizes. Yay!
/** * fix broken image metadata so that thumbs can be regenerated */ function fixImageMeta() { global $wpdb; $sql = " select ID from {$wpdb->posts} where post_type = 'attachment' and post_mime_type like 'image/%' "; $images = $wpdb->get_col($sql); foreach ($images as $id) { $meta = wp_get_attachment_metadata($id); if (!$meta) { $file = get_attached_file($id); if (!empty($file)) { $info = getimagesize($file); $meta = array ( 'width' => $info[0], 'height' => $info[1], 'hwstring_small' => "height='{$info[1]}' width='{$info[0]}'", 'file' => basename($file), 'sizes' => array(), // thumbnails etc. 'image_meta' => array(), // EXIF data ); update_post_meta($id, '_wp_attachment_metadata', $meta); } } } }