WordPress重新生成图片的缩略图

通常都是采用插件的方式来实现这个功能,但是我一直喜欢使用代码的方式来解决问题。首先我参照了一篇文章https://www.gavsblog.com/blog/regenerate-wordpress-media-image-sizes-programmaticall,他的代码如下:

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

// Put the function in a class to make it more extendable
class GB_regen_media {
    public function gb_regenerate($imageId) {
        $imagePath = wp_get_original_image_path($imageId);

        if ($imagePath && file_exists($imagePath)) {
            wp_generate_attachment_metadata($imageId, $imagePath);
        }
    }
}

// Add a load function
function gb_regen_load() {
    // Instantiate the class
    $gb_regen_media = new GB_regen_media();

    // Set the image Id
    $imageId = 1;

    // You can get the image Id from the url of the media screen
    $gb_regen_media->gb_regenerate($imageId);
}

// Load after WordPress has finished loading
add_action('init', 'gb_regen_load');

这里边用到了几个函数功能:wp_get_original_image_path($imageId)wp_generate_attachment_metadata($imageId, $imagePath)以及add_action('init', 'gb_regen_load')

我这里需要考虑所有上传的图片附件,所以修改了一下代码:

// Put the function in a class to make it more extendable
class GB_regen_media {
    public function gb_regenerate($imageId) {
        $imagePath = wp_get_original_image_path($imageId);

        if ($imagePath && file_exists($imagePath)) {
            // unlink();
            wp_generate_attachment_metadata($imageId, $imagePath);
        }
    }
}

// Add a load function
function gb_regen_load($new_value,$old_value) {
    // Instantiate the class
    $gb_regen_media = new GB_regen_media();

    $regenerate_thumbnail_value = get_option('xcm_regenerate_thumbnail_enable', '');
    $args = array('post_type'=>'attachment','numberposts'=>null,'post_status'=>null);
    $attachments = get_posts($args);

    // You can get the image Id from the url of the media screen
    if($attachments && $new_value == '1'){
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $new_value = '';
        foreach($attachments as $attachment){
            $gb_regen_media->gb_regenerate($attachment->ID);
        }
    }
    return $new_value;
}
add_filter('pre_update_option_regenerate_thumbnail_enable', 'gb_regen_load',10,2);

此处代码的重点在于选择哪一种钩子(hook),这里列举三种:

一种是add_action('updated_option',functions),它将在任意option更新之后被激发,这是不必要的。

第二种是add_action('update_option_{$option}',function),需要注意新旧参数值( $old_value, $new_value )的前后位置,示例代码如下:

add_action( 'update_option_myoption', function( $old_value, $new_value ) {
   //Do something with the new value
}, 10, 2);

但是这一方法并不能修改新的值,当新旧值完全一样时不会被触发,这一点在官方页面中有所提及:https://developer.wordpress.org/reference/hooks/update_option_option/

第三种是pre_update_option_{$option},示例代码如下:

add_filter( 'pre_update_option_myoption', function( $new_value, $old_value ) {

   //Do something before returning the new value to be saved in database

   return $new_value;

}, 10, 2);

我这里使用的就是这一种,它有一个好处就是能够查看新旧值并修改新值,我的逻辑是这样,首先判断”regenerate_thumbnail_enable”的新值,是否为1,为1就是运行,不为1就是不需要重新生成缩略图,如果新值为1,那么我们就运行相关功能函数,并且将新值改成空值,这样就能避免该功能在不必要的情况下被触发。

但是仍然存在一个问题,就是函数wp_generate_attachment_metadata($imageId, $imagePath)会将所有注册过的缩略图尺寸重新生成一遍,显的不那么节省资源;此外,无用缩略图的的清理也是一个问题,不过我们可以在新缩略图生成之后,通过后台文件检索进行删除。