分析 WordPress `wp_get_image_editor()` 函数的源码:它如何根据服务器环境选择合适的图片编辑器(如 GD 或 Imagick),并封装为统一的接口。

WordPress 图片编辑器的幕后英雄:wp_get_image_editor() 深度解析

各位朋友,大家好!我是老码农,今天咱们来聊聊 WordPress 里一个经常被忽略,但又非常重要的函数:wp_get_image_editor()。 它就像一位幕后英雄,默默地帮我们处理图片编辑的各种脏活累活,让我们在 WordPress 后台可以轻松地裁剪、缩放图片。

你可能觉得奇怪,图片处理不就是裁剪、缩放嘛,有啥复杂的?嘿,这里面的水可深着呢。不同的服务器环境,支持的图片处理库可能不一样,有的用 GD 库,有的用 Imagick。更麻烦的是,即使都支持,它们的用法、参数、效果也可能千差万别。

如果让我们自己去判断用哪个库,然后针对不同的库写不同的代码,那简直是噩梦!幸好,WordPress 的开发者们早就想到了这一点,他们用 wp_get_image_editor() 这个函数,把这些差异都封装起来了,给我们提供了一个统一的接口。

今天,咱们就来扒一扒 wp_get_image_editor() 的源码,看看它是如何根据服务器环境选择合适的图片编辑器,并封装成统一的接口的。准备好了吗?咱们开始!

1. 初探 wp_get_image_editor():你以为它很简单?

首先,我们来看看 wp-includes/media.php 文件里 wp_get_image_editor() 函数的庐山真面目:

function wp_get_image_editor( $file, $args = array() ) {
    /**
     * Filters the list of available image editors.
     *
     * @since 3.5.0
     *
     * @param string[] $editors An array of available image editors.
     */
    $implementations = apply_filters( 'wp_image_editors', array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );

    if ( empty( $implementations ) ) {
        return new WP_Error( 'image_no_editor', __( 'No image editor available.' ) );
    }

    foreach ( $implementations as $implementation ) {
        if ( ! is_subclass_of( $implementation, 'WP_Image_Editor' ) ) {
            continue;
        }

        if ( call_user_func( array( $implementation, 'test' ) ) ) {
            $editor = new $implementation( $file, $args );
            if ( is_wp_error( $editor->get_error_code() ) && $editor->get_error_code() !== 'error_loading_image' ) {
                continue;
            }
            return $editor;
        }
    }

    return new WP_Error( 'image_no_editor', __( 'No image editor available.' ) );
}

是不是觉得有点眼花缭乱?没关系,我们一步一步来分析。

  • $file 参数: 不用说,这是你要编辑的图片文件的路径。
  • $args 参数: 可选参数,可以传递一些额外的配置信息,比如质量、大小等等。
  • $implementations 数组: 这个数组里存放的是 WordPress 支持的图片编辑器类名。默认情况下,包含了 WP_Image_Editor_ImagickWP_Image_Editor_GD,分别代表 Imagick 和 GD 库。注意,这里用到了 apply_filters 钩子,允许我们通过插件或主题来修改这个列表,添加或删除图片编辑器。
  • 循环遍历: 函数会遍历 $implementations 数组,依次尝试使用每个图片编辑器。
  • is_subclass_of() 首先,它会检查当前的类是否是 WP_Image_Editor 的子类。 WP_Image_Editor 是一个抽象类,定义了图片编辑器必须实现的一些基本方法。
  • test() 方法: 关键的一步来了! call_user_func( array( $implementation, 'test' ) ) 会调用当前图片编辑器类的 test() 静态方法,来判断服务器环境是否支持该编辑器。
  • 实例化编辑器: 如果 test() 方法返回 true,表示支持,那么就实例化该编辑器,并返回。
  • 错误处理: 如果在实例化过程中出现错误(比如图片加载失败),则继续尝试下一个编辑器。
  • 找不到编辑器: 如果所有编辑器都尝试失败,则返回一个 WP_Error 对象,提示找不到可用的图片编辑器。

看到这里,你可能已经明白了 wp_get_image_editor() 的大致工作流程:它会根据 $implementations 数组,依次尝试使用每个图片编辑器,直到找到一个可用的为止。

2. WP_Image_Editor 抽象类:定义统一接口

刚才我们提到了 WP_Image_Editor 抽象类,它是所有图片编辑器类的基类,定义了统一的接口。 让我们来看看它的源码(位于 wp-includes/class-wp-image-editor.php):

abstract class WP_Image_Editor {

    /**
     * File being manipulated.
     *
     * @since 3.5.0
     * @var string
     */
    protected $file;

    /**
     * Original image width.
     *
     * @since 3.5.0
     * @var int
     */
    protected $width;

    /**
     * Original image height.
     *
     * @since 3.5.0
     * @var int
     */
    protected $height;

    /**
     * Image quality.
     *
     * @since 3.5.0
     * @var int
     */
    protected $quality;

    /**
     * Stores whether errors have occurred.
     *
     * @since 3.5.0
     * @var WP_Error
     */
    protected $errors;

    /**
     * PHP4 constructor.
     *
     * @deprecated 3.5.0 Use __construct() instead.
     */
    public function WP_Image_Editor( $file ) {
        _deprecated_constructor( __CLASS__, '3.5.0', 'WP_Image_Editor::__construct()' );
        self::__construct( $file );
    }

    /**
     * WP_Image_Editor constructor.
     *
     * @since 3.5.0
     *
     * @param string $file Filename of the image to load.
     */
    public function __construct( $file ) {
        $this->file   = $file;
        $this->errors = new WP_Error();
    }

    /**
     * Checks to see if there are any errors.
     *
     * @since 3.5.0
     *
     * @return string|false Error message on failure. False on success.
     */
    public function get_error_message() {
        if ( ! is_wp_error( $this->errors ) ) {
            return false;
        }

        return $this->errors->get_error_message();
    }

    /**
     * Returns a WP_Error object containing any errors.
     *
     * @since 3.5.0
     *
     * @return WP_Error WP_Error object.
     */
    public function get_error() {
        return $this->errors;
    }

    /**
     * Returns an error code if one exists.
     *
     * @since 4.6.0
     *
     * @return string|false Error code on failure. False on success.
     */
    public function get_error_code() {
        if ( ! is_wp_error( $this->errors ) ) {
            return false;
        }

        return $this->errors->get_error_code();
    }

    /**
     * Checks to see if there are any errors.
     *
     * @since 3.5.0
     *
     * @return bool True if there are errors.
     */
    public function has_errors() {
        return (bool) count( $this->errors->get_error_codes() );
    }

    /**
     * Adds an error.
     *
     * @since 3.5.0
     *
     * @param string|WP_Error $code    Error code.
     * @param string          $message Error message.
     */
    public function add_error( $code, $message = '' ) {
        if ( is_wp_error( $code ) ) {
            $this->errors->add( $code->get_error_code(), $code->get_error_message() );
        } else {
            $this->errors->add( $code, $message );
        }
    }

    /**
     * Removes all errors.
     *
     * @since 3.5.0
     */
    public function remove_error() {
        $this->errors = new WP_Error();
    }

    /**
     * Sets the file property.
     *
     * @since 3.5.0
     *
     * @param string $file Path to the original image file.
     */
    public function set_file( $file ) {
        $this->file = $file;
    }

    /**
     * Loads an image resource for editing.
     *
     * @since 3.5.0
     *
     * @return true|WP_Error True if loaded successfully. WP_Error on failure.
     */
    abstract public function load();

    /**
     * Saves current image to file.
     *
     * @since 3.5.0
     *
     * @param string|null $destfilename Optional. String containing the file name to save to. Defaults to the original file.
     * @param string|null $mime_type    Optional. Image mime type. Defaults to the mime type of the file.
     *
     * @return array|WP_Error Array containing new width, height, and file name on success. WP_Error object on failure.
     */
    abstract public function save( $destfilename = null, $mime_type = null );

    /**
     * Resizes current image.
     *
     * @since 3.5.0
     *
     * @param int|null $max_w Optional. Maximum width.
     * @param int|null $max_h Optional. Maximum height.
     * @param bool     $crop  Optional. Whether to crop image to specified dimensions.
     *
     * @return true|WP_Error True if resize is successful. WP_Error on failure.
     */
    abstract public function resize( $max_w = null, $max_h = null, $crop = false );

    /**
     * Returns current image dimensions.
     *
     * @since 3.5.0
     *
     * @return array|WP_Error Associative array width and height on success. WP_Error on failure.
     */
    abstract public function get_size();

    /**
     * Resizes and crops current image.
     *
     * @since 3.5.0
     *
     * @param int $dst_x The start x coordinate to crop from.
     * @param int $dst_y The start y coordinate to crop from.
     * @param int $src_w The width to crop.
     * @param int $src_h The height to crop.
     * @param int $dst_w The destination width.
     * @param int $dst_h The destination height.
     * @param bool $crop Whether to crop the image.
     *
     * @return true|WP_Error True on success. WP_Error on failure.
     */
    abstract public function crop( $dst_x, $dst_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $crop = false );

    /**
     * Rotates current image.
     *
     * @since 3.5.0
     *
     * @param float $angle Angle in degrees to rotate.
     *
     * @return true|WP_Error True on success. WP_Error on failure.
     */
    abstract public function rotate( $angle );

    /**
     * Flips current image.
     *
     * @since 3.5.0
     *
     * @param bool $horz Flip along the horizontal axis.
     * @param bool $vert Flip along the vertical axis.
     *
     * @return true|WP_Error True on success. WP_Error on failure.
     */
    abstract public function flip( $horz, $vert );

    /**
     * Saves current image to file.
     *
     * @since 3.5.0
     *
     * @param string $filename  Filename of the destination image.
     * @param string $mime_type The image mimetype.
     *
     * @return array|WP_Error Array containing new width, height, and file name on success. WP_Error object on failure.
     */
    abstract public function stream( $mime_type = null );

    /**
     * Sets the quality of the image.
     *
     * @since 3.5.0
     *
     * @param int $quality Compression quality values from 0 (worst) to 100 (best).
     *
     * @return true|WP_Error True if set successfully. WP_Error on failure.
     */
    public function set_quality( $quality ) {
        if ( is_int( $quality ) && $quality >= 0 && $quality <= 100 ) {
            $this->quality = $quality;

            return true;
        }

        return new WP_Error( 'invalid_image_quality', __( 'Image quality must be a number between 0 and 100.' ) );
    }

    /**
     * Gets the quality of the image.
     *
     * @since 3.5.0
     *
     * @return int Returns the image quality.
     */
    public function get_quality() {
        return $this->quality;
    }

    /**
     * Test to see if an editor is usable.
     *
     * @since 3.5.0
     *
     * @param array $args Array of strings for extra information.
     * @return bool True if editor is valid.
     */
    public static function test( $args = array() ) {
        return false;
    }
}

这个抽象类定义了一些基本的属性,比如 $file(图片文件路径)、$width(图片宽度)、$height(图片高度)、$quality(图片质量)等等。

更重要的是,它定义了一系列抽象方法,比如 load()save()resize()crop()rotate()flip()stream() 等等。这些方法是图片编辑器必须实现的,用来完成各种图片编辑操作。

简单来说,WP_Image_Editor 就像一个接口规范,它规定了所有图片编辑器必须提供哪些功能。 这样,我们就可以用统一的方式来调用不同的图片编辑器,而不用关心它们底层的实现细节。

3. WP_Image_Editor_GD:GD 库的实现

接下来,我们来看看 WP_Image_Editor_GD 类,它是 WP_Image_Editor 抽象类的具体实现,用来使用 GD 库进行图片编辑。 它的源码位于 wp-includes/class-wp-image-editor-gd.php

由于篇幅限制,我们只挑几个关键的方法来分析:

  • test() 方法: 这个方法用来判断服务器环境是否支持 GD 库。
    /**
     * Checks to see if current environment supports the GD library.
     *
     * @since 3.5.0
     *
     * @param array $args Not used.
     * @return bool
     */
    public static function test( $args = array() ) {
        if ( ! function_exists( 'imagecreatetruecolor' ) ) {
            return false;
        }

        if ( ! function_exists( 'imagecopyresampled' ) ) {
            return false;
        }

        return true;
    }

可以看到,它主要检查 imagecreatetruecolor()imagecopyresampled() 这两个函数是否存在。如果这两个函数都存在,就说明 GD 库可用。

  • load() 方法: 这个方法用来加载图片文件,并创建 GD 图像资源。
    /**
     * Loads an image resource for editing.
     *
     * @since 3.5.0
     *
     * @return true|WP_Error True if loaded successfully. WP_Error on failure.
     */
    public function load() {
        if ( ! is_readable( $this->file ) ) {
            return new WP_Error( 'image_file_missing', __( 'File does not exist.' ) );
        }

        $this->image = wp_load_image( $this->file );

        if ( is_wp_error( $this->image ) ) {
            return $this->image;
        }

        $this->size = @getimagesize( $this->file );

        if ( ! $this->size ) {
            return new WP_Error( 'invalid_image', __( 'Could not read image size.' ) );
        }

        $this->width  = $this->size[0];
        $this->height = $this->size[1];

        return true;
    }

这里用到了 wp_load_image() 函数来加载图片。 wp_load_image() 会根据图片类型,调用不同的 GD 函数来创建图像资源。 比如,如果是 JPEG 图片,就调用 imagecreatefromjpeg();如果是 PNG 图片,就调用 imagecreatefrompng()

  • resize() 方法: 这个方法用来缩放图片。
    /**
     * Resizes current image.
     *
     * @since 3.5.0
     *
     * @param int|null $max_w Optional. Maximum width.
     * @param int|null $max_h Optional. Maximum height.
     * @param bool     $crop  Optional. Whether to crop image to specified dimensions.
     *
     * @return true|WP_Error True if resize is successful. WP_Error on failure.
     */
    public function resize( $max_w = null, $max_h = null, $crop = false ) {
        if ( ( $this->width == $max_w ) && ( $this->height == $max_h ) ) {
            return true;
        }

        $dims = image_resize_dimensions( $this->width, $this->height, $max_w, $max_h, $crop );
        if ( ! $dims ) {
            return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ) );
        }
        list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;

        $new_image = imagecreatetruecolor( $dst_w, $dst_h );
        imagealphablending( $new_image, false );
        imagesavealpha( $new_image, true );
        $result = imagecopyresampled( $new_image, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );

        if ( ! $result ) {
            return new WP_Error( 'image_resize_failed', __( 'Image resize failed.' ) );
        }

        imagedestroy( $this->image );

        $this->image  = $new_image;
        $this->width  = $dst_w;
        $this->height = $dst_h;

        return true;
    }

这里用到了 image_resize_dimensions() 函数来计算缩放后的尺寸。 然后,它创建了一个新的 GD 图像资源,并使用 imagecopyresampled() 函数将原图复制到新图中,完成缩放操作。

  • save() 方法: 这个方法用来保存图片文件。
    /**
     * Saves current image to file.
     *
     * @since 3.5.0
     *
     * @param string|null $destfilename Optional. String containing the file name to save to. Defaults to the original file.
     * @param string|null $mime_type    Optional. Image mime type. Defaults to the mime type of the file.
     *
     * @return array|WP_Error Array containing new width, height, and file name on success. WP_Error object on failure.
     */
    public function save( $destfilename = null, $mime_type = null ) {
        if ( ! $destfilename ) {
            $destfilename = $this->file;
        }

        if ( ! $mime_type ) {
            $mime_type = $this->get_mime_type( $destfilename );
        }

        $quality = $this->get_quality();

        if ( 'image/jpeg' == $mime_type ) {
            if ( ! @imagejpeg( $this->image, $destfilename, $quality ) ) {
                return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
            }
        } elseif ( 'image/png' == $mime_type ) {
            // See https://wordpress.org/support/topic/gd-library-does-not-handle-transparency-well/.
            if ( ! defined( 'PNG_FILTER_NONE' ) ) {
                define( 'PNG_FILTER_NONE', 0 );
            }

            if ( ! @imagepng( $this->image, $destfilename, round( $quality / 10 ) ) ) {
                return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
            }
        } elseif ( 'image/gif' == $mime_type ) {
            if ( ! @imagegif( $this->image, $destfilename ) ) {
                return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
            }
        } else {
            return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
        }

        imagedestroy( $this->image );

        /** This filter is documented in wp-includes/class-wp-image-editor.php */
        return apply_filters( 'image_save_pre_send_to_editor', array(
            'file'   => $destfilename,
            'width'  => $this->width,
            'height' => $this->height,
        ), $this->id );
    }

这里根据图片类型,调用不同的 GD 函数来保存图片。 比如,如果是 JPEG 图片,就调用 imagejpeg();如果是 PNG 图片,就调用 imagepng()

总而言之,WP_Image_Editor_GD 类封装了 GD 库的各种函数,实现了 WP_Image_Editor 抽象类定义的接口。

4. WP_Image_Editor_Imagick:Imagick 的实现

类似地,WP_Image_Editor_Imagick 类也是 WP_Image_Editor 抽象类的具体实现,用来使用 Imagick 库进行图片编辑。 它的源码位于 wp-includes/class-wp-image-editor-imagick.php

我们还是挑几个关键的方法来分析:

  • test() 方法: 这个方法用来判断服务器环境是否支持 Imagick 库。
    /**
     * Checks to see if current environment supports the Imagick library.
     *
     * @since 3.5.0
     *
     * @param array $args Not used.
     * @return bool
     */
    public static function test( $args = array() ) {
        if ( ! extension_loaded( 'imagick' ) ) {
            return false;
        }

        if ( ! class_exists( 'Imagick' ) ) {
            return false;
        }

        $required_version = '6.2.4';

        if ( defined( 'imagick::IMAGICK_EXTNUM' ) && imagick::IMAGICK_EXTNUM < 2000 ) {
            return false;
        }

        if ( version_compare( phpversion( 'imagick' ), $required_version, '<' ) ) {
            return false;
        }

        return true;
    }

可以看到,它主要检查 imagick 扩展是否加载,以及 Imagick 的版本是否符合要求。

  • load() 方法: 这个方法用来加载图片文件,并创建 Imagick 对象。
    /**
     * Loads an image resource for editing.
     *
     * @since 3.5.0
     *
     * @return true|WP_Error True if loaded successfully. WP_Error on failure.
     */
    public function load() {
        if ( ! is_readable( $this->file ) ) {
            return new WP_Error( 'image_file_missing', __( 'File does not exist.' ) );
        }

        try {
            $this->image = new Imagick( $this->file );

            if ( ! is_object( $this->image ) ) {
                return new WP_Error( 'invalid_image', __( 'Could not read image.' ) );
            }

            if ( is_callable( array( $this->image, 'setImageOrientation' ) ) ) {
                $this->image->setImageOrientation( imagick::ORIENTATION_TOPLEFT );
            }

            /*
             * Strip profiles if not a whitelisted file type. Prevents image
             * corruption issues.
             */
            $strip = true;

            $whitelisted_mimes = array(
                'image/jpeg',
                'image/png',
                'image/gif',
                'image/bmp',
                'image/tiff',
            );

            $whitelisted_exts = array(
                'jpg',
                'jpeg',
                'png',
                'gif',
                'bmp',
                'tif',
                'tiff',
            );

            $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
            $mime_type = $this->get_mime_type( $this->file );

            if ( in_array( $mime_type, $whitelisted_mimes, true ) && in_array( $file_ext, $whitelisted_exts, true ) ) {
                $strip = false;
            }

            if ( $strip ) {
                $this->strip_image();
            }

            $this->unstrip();

            $this->set_defaults();

            $this->width  = $this->image->getImageWidth();
            $this->height = $this->image->getImageHeight();

            return true;
        } catch ( Exception $e ) {
            return new WP_Error( 'invalid_image', $e->getMessage() );
        }
    }

这里直接使用 new Imagick() 来创建一个 Imagick 对象。

  • resize() 方法: 这个方法用来缩放图片。
    /**
     * Resizes current image.
     *
     * @since 3.5.0
     *
     * @param int|null $max_w Optional. Maximum width.
     * @param int|null $max_h Optional. Maximum height.
     * @param bool     $crop  Optional. Whether to crop image to specified dimensions.
     *
     * @return true|WP_Error True if resize is successful. WP_Error on failure.
     */
    public function resize( $max_w = null, $max_h = null, $crop = false ) {
        if ( ( $this->width == $max_w ) && ( $this->height == $max_h ) ) {
            return true;
        }

        $dims = image_resize_dimensions( $this->width, $this->height, $max_w, $max_h, $crop );
        if ( ! $dims ) {
            return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ) );
        }
        list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;

        if ( $crop ) {
            return $this->crop( $dst_x, $dst_y, $src_w, $src_h, $dst_w, $dst_h );
        }

        $thumb = $this->image->clone();

        /**
         * Note: setResourceLimit() is only available since Imagick 6.3.7.
         * See: https://bugs.php.net/bug.php?id=43777
         */
        if ( is_callable( array( $thumb, 'setResourceLimit' ) ) ) {
            $thumb->setResourceLimit( Imagick::RESOURCETYPE_MEMORY, $max_w * $max_h * 8 );
        }

        $thumb->setImageInterpolateMethod( Imagick::INTERPOLATE_BICUBIC );
        $thumb->resizeImage( $dst_w, $dst_h, Imagick::FILTER_LANCZOS, 1 );

        $thumb->setImagePage( 0, 0, 0, 0 );

        $this->image->clear();
        $this->image->destroy();
        $this->image = $thumb;

        $this->width  = $dst_w;
        $this->height = $dst_h;

        return true;
    }

这里用到了 Imagick::resizeImage() 函数来缩放图片。

  • save() 方法: 这个方法用来保存图片文件。
    /**
     * Saves current image to file.
     *
     * @since 3.5.0
     *
     * @param string|null $destfilename Optional. String containing the file name to save to. Defaults to the original file.
     * @param string|null $mime_type    Optional. Image mime type. Defaults to the mime type of the file.
     *
     * @return array|WP_Error Array containing new width, height, and file name on success. WP_Error object on failure.
     */
    public function save( $destfilename = null, $mime_type = null ) {
        if ( ! $destfilename ) {
            $destfilename = $this->file;
        }

        if ( ! $mime_type ) {
            $mime_type = $this->get_mime_type( $destfilename );
        }

        $quality = $this->get_quality();

        try {
            if ( ! empty( $quality ) ) {
                $this->image->setImageCompressionQuality( $quality );
            }

            /*
             * Prevent Imagick from writing EXIF data into PNG files.
             *
             * See https://wordpress.org/support/topic/image-rotation-issue-with-wp-4-6.
             */
            if ( 'image/png' === $mime_type ) {
                $this->image->stripImage();
            }

            if ( 'image/jpeg' === $mime_type && defined( 'WP_IMAGE_EDIT_JPEG_QUALITY' ) ) {
                $this->image->setImageCompressionQuality( WP_IMAGE_EDIT_JPEG_QUALITY );
            }

            if ( ! $this->image->writeImage( $destfilename ) ) {
                return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
            }

            $this->set_defaults();

            /** This filter is documented in wp-includes/class-wp-image-editor.php */
            return apply_filters( 'image_save_pre_send_to_editor', array(
                'file'   => $destfilename,
                'width'  => $this->width,
                'height' => $this->height,
            ), $this->id );
        } catch ( Exception $e ) {
            return new WP_Error( 'image_save_error', $e->getMessage() );
        }
    }

这里使用 Imagick::writeImage() 函数来保存图片。

同样,WP_Image_Editor_Imagick 类封装了 Imagick 库的各种函数,实现了 WP_Image_Editor 抽象类定义的接口。

5. 总结:wp_get_image_editor() 的价值

通过以上的源码分析,我们可以看到 wp_get_image_editor() 函数的价值所在:

  • 屏蔽了底层图片处理库的差异: 无论是 GD 还是 Imagick,它们都有自己的 API 和用法。wp_get_image_editor() 让我们不用关心这些差异,只需要调用统一的 WP_Image_Editor 接口即可。
  • 提高了代码的可维护性和可扩展性: 如果我们需要添加新的图片编辑器(比如使用一个新的图片处理库),只需要实现 WP_Image_Editor 抽象类,并将其添加到 $implementations 数组中即可。
  • 简化了图片处理流程: 我们可以用简单的几行代码,就可以完成复杂的图片编辑操作。

为了更清晰地展示 wp_get_image_editor() 的作用,我们用一个表格来总结一下:

| 函数/类名 | 作用

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注