分析 `wp_get_attachment_image_src()` 函数的源码,它如何从 `_wp_attachment_metadata` 中获取图片尺寸信息?

哈喽大家好!今天咱们来聊聊 WordPress 里一个常用的函数:wp_get_attachment_image_src()。这玩意儿能帮我们获取附件图片的 URL、宽度和高度,简直是前端开发的得力助手。

今天的主题是:wp_get_attachment_image_src() 如何从 _wp_attachment_metadata 中"扒"出图片尺寸信息?

准备好了吗?咱们开始!

1. 剧情背景:wp_get_attachment_image_src() 的身世

wp_get_attachment_image_src() 函数,顾名思义,就是获取附件图片的源文件信息。它主要接收两个参数(当然还有可选参数):

  • $attachment_id:附件的 ID,也就是文章 ID。
  • $size:图片尺寸。可以是 ‘thumbnail’,’medium’,’large’,’full’,或者一个自定义的尺寸名称,甚至是一个包含宽度和高度的数组。

这个函数最终会返回一个数组,里面包含图片的 URL、宽度和高度。如果找不到对应尺寸的图片,它可能会返回 false

2. 源码剖析:步步惊心

咱们直接上源码(简化版,去掉了错误处理和钩子):

function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) {
    $image = false;
    // 1. 获取附件的元数据
    $image_src = get_attached_file( $attachment_id, true );

    $meta = wp_get_attachment_metadata( $attachment_id );

    // 2. 如果没有元数据,直接返回false
    if ( empty( $meta ) ) {
        return false;
    }

    // 3. 处理 'full' 尺寸
    if ( 'full' === $size ) {
        $src = wp_get_attachment_url( $attachment_id );
        $width = $meta['width'];
        $height = $meta['height'];

        return array( $src, $width, $height, true );
    }

    // 4. 处理自定义尺寸
    if ( is_array( $size ) ) {
        $width  = intval( $size[0] );
        $height = intval( $size[1] );
        if ( isset( $meta['sizes']['resized'] ) ) {
            $src = wp_get_attachment_url( $attachment_id );
            return array( $src, $width, $height, true );
        }

    }

    // 5. 处理预定义尺寸
    if ( isset( $meta['sizes'][ $size ] ) ) {
        $src = wp_get_attachment_url( $attachment_id );
        $src_data = $meta['sizes'][ $size ];
        $src = dirname( $src ) . '/' . $src_data['file'];

        $width = $src_data['width'];
        $height = $src_data['height'];

        return array( $src, $width, $height, true );
    }

    return false;
}

让我们一步步来分析这段代码:

第一步:获取元数据

$meta = wp_get_attachment_metadata( $attachment_id );

这是关键的一步!wp_get_attachment_metadata() 函数会从数据库中获取附件的元数据。这些元数据都存储在文章的 _wp_attachment_metadata 自定义字段里,以序列化的数组形式存在。

第二步:检查元数据是否存在

if ( empty( $meta ) ) {
    return false;
}

如果没有元数据,那就意味着这个附件可能不是图片,或者元数据丢失了。这时候,函数会直接返回 false

第三步:处理 full 尺寸

if ( 'full' === $size ) {
    $src = wp_get_attachment_url( $attachment_id );
    $width = $meta['width'];
    $height = $meta['height'];

    return array( $src, $width, $height, true );
}

如果请求的尺寸是 'full',也就是原始尺寸,那么函数会直接从元数据的 'width''height' 字段中获取宽度和高度。 wp_get_attachment_url 获取原始图片的 URL。

第四步:处理自定义尺寸

if ( is_array( $size ) ) {
        $width  = intval( $size[0] );
        $height = intval( $size[1] );
        if ( isset( $meta['sizes']['resized'] ) ) {
            $src = wp_get_attachment_url( $attachment_id );
            return array( $src, $width, $height, true );
        }

    }

如果 $size 是一个数组,比如 array(100, 100),那么函数会把数组的第一个元素当做宽度,第二个元素当做高度。 这个条件 isset( $meta['sizes']['resized'] ) 有点奇怪,通常自定义尺寸不会存在 ‘resized’ 这个键,这个可能是一个历史遗留问题或者特定主题/插件的实现。 理论上自定义尺寸应该返回false,表示没有这个尺寸, 但是这里直接返回了原始图片的URL和传入的宽高值,算是一个潜在的bug。

第五步:处理预定义尺寸

if ( isset( $meta['sizes'][ $size ] ) ) {
    $src = wp_get_attachment_url( $attachment_id );
    $src_data = $meta['sizes'][ $size ];
    $src = dirname( $src ) . '/' . $src_data['file'];

    $width = $src_data['width'];
    $height = $src_data['height'];

    return array( $src, $width, $height, true );
}

这是最常见的情况。如果请求的尺寸是 'thumbnail''medium''large' 等预定义的尺寸,那么函数会从元数据的 'sizes' 数组中查找对应的尺寸信息。

$meta['sizes'][ $size ] 会返回一个数组,包含该尺寸的 'file'(文件名)、'width'(宽度)和 'height'(高度)。

然后,函数会根据文件名拼接出图片的 URL,并返回包含 URL、宽度和高度的数组。

3. _wp_attachment_metadata 的秘密

现在,让我们深入了解一下 _wp_attachment_metadata 这个自定义字段里到底藏着什么秘密。

假设我们上传了一张名为 my-image.jpg 的图片。WordPress 会自动生成几个不同尺寸的缩略图,并将这些信息存储在 _wp_attachment_metadata 中。

这个字段的值是一个序列化的数组,反序列化后大概是这个样子:

array(
    'width' => 1024, // 原始图片的宽度
    'height' => 768, // 原始图片的高度
    'file' => '2023/10/my-image.jpg', // 原始图片的文件路径(相对于 uploads 目录)
    'sizes' => array(
        'thumbnail' => array(
            'file' => 'my-image-150x150.jpg',
            'width' => 150,
            'height' => 150,
            'mime-type' => 'image/jpeg',
        ),
        'medium' => array(
            'file' => 'my-image-300x225.jpg',
            'width' => 300,
            'height' => 225,
            'mime-type' => 'image/jpeg',
        ),
        'large' => array(
            'file' => 'my-image-1024x768.jpg',
            'width' => 1024,
            'height' => 768,
            'mime-type' => 'image/jpeg',
        ),
        // ... 其他尺寸
    ),
    'image_meta' => array(
        // EXIF 信息
    ),
)

可以看到,_wp_attachment_metadata 包含了原始图片的宽度、高度、文件路径,以及各种尺寸的缩略图信息。

4. 代码示例:实战演练

假设我们有一个附件 ID 为 123。我们可以这样使用 wp_get_attachment_image_src() 函数:

$attachment_id = 123;

// 获取 'thumbnail' 尺寸的图片信息
$thumbnail_image = wp_get_attachment_image_src( $attachment_id, 'thumbnail' );

if ( $thumbnail_image ) {
    $url = $thumbnail_image[0]; // 图片的 URL
    $width = $thumbnail_image[1]; // 图片的宽度
    $height = $thumbnail_image[2]; // 图片的高度

    echo '<img src="' . esc_url( $url ) . '" width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" alt="Thumbnail">';
} else {
    echo 'Thumbnail not found.';
}

// 获取 'medium' 尺寸的图片信息
$medium_image = wp_get_attachment_image_src( $attachment_id, 'medium' );

if ( $medium_image ) {
    $url = $medium_image[0]; // 图片的 URL
    $width = $medium_image[1]; // 图片的宽度
    $height = $medium_image[2]; // 图片的高度

    echo '<img src="' . esc_url( $url ) . '" width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" alt="Medium">';
} else {
    echo 'Medium not found.';
}

// 获取 'full' 尺寸的图片信息
$full_image = wp_get_attachment_image_src( $attachment_id, 'full' );

if ( $full_image ) {
    $url = $full_image[0]; // 图片的 URL
    $width = $full_image[1]; // 图片的宽度
    $height = $full_image[2]; // 图片的高度

    echo '<img src="' . esc_url( $url ) . '" width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" alt="Full">';
} else {
    echo 'Full image not found.';
}

// 获取自定义尺寸的图片信息
$custom_image = wp_get_attachment_image_src( $attachment_id, array( 500, 300 ) );

if ( $custom_image ) {
    $url = $custom_image[0]; // 图片的 URL
    $width = $custom_image[1]; // 图片的宽度
    $height = $custom_image[2]; // 图片的高度

    echo '<img src="' . esc_url( $url ) . '" width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" alt="Custom">';
} else {
    echo 'Custom image not found.';
}

5. 总结:wp_get_attachment_image_src() 的工作流程

为了更清晰地理解 wp_get_attachment_image_src() 的工作流程,我们可以用一个表格来总结:

步骤 描述 涉及的变量
1 获取附件的元数据 (_wp_attachment_metadata)。 $attachment_id, $meta
2 检查元数据是否存在。如果不存在,返回 false $meta
3 如果 $size'full',从 $meta['width']$meta['height'] 获取宽度和高度,并返回包含 URL、宽度和高度的数组。 $size, $meta['width'], $meta['height'], $src
4 如果 $size 是一个数组,从 $size[0]$size[1] 获取宽度和高度,如果 isset( $meta['sizes']['resized'] ) 存在,则返回包含URL、宽度和高度的数组。 $size, $size[0], $size[1], $meta['sizes']['resized'], $src
5 如果 $size 是预定义的尺寸(例如 'thumbnail''medium''large'),从 $meta['sizes'][ $size ] 获取尺寸信息,包括文件名、宽度和高度。根据文件名拼接出图片的 URL,并返回包含 URL、宽度和高度的数组。 $size, $meta['sizes'][ $size ], $meta['sizes'][ $size ]['file'], $meta['sizes'][ $size ]['width'], $meta['sizes'][ $size ]['height'], $src
6 如果以上条件都不满足,返回 false

6. 避坑指南:注意事项

  • 确保附件存在: 在使用 wp_get_attachment_image_src() 之前,一定要确保 $attachment_id 是一个有效的附件 ID。
  • 尺寸名称要匹配: 如果使用预定义的尺寸名称,一定要确保名称是正确的(例如 'thumbnail''medium''large')。大小写敏感。
  • 自定义尺寸: 如果需要使用自定义尺寸,可以先使用 add_image_size() 函数注册自定义尺寸,然后 WordPress 会自动生成对应的缩略图并存储在 _wp_attachment_metadata 中。
  • 图片路径: wp_get_attachment_image_src() 返回的 URL 是相对于 WordPress 根目录的。如果需要完整的 URL,可以使用 site_url() 函数拼接。

7. 进阶技巧:自定义尺寸生成

有时候,WordPress 默认的缩略图尺寸可能无法满足我们的需求。这时候,我们可以使用 add_image_size() 函数来注册自定义尺寸。

add_image_size( 'my-custom-size', 500, 300, true ); // 注册一个名为 'my-custom-size' 的尺寸,宽度为 500px,高度为 300px,裁剪模式为 true

这段代码会将宽度超过 500px,高度超过 300px 的图片裁剪成 500×300 的尺寸。

然后,我们需要重新生成缩略图。可以使用 Regenerate Thumbnails 插件来完成这个任务。

之后,我们就可以使用 wp_get_attachment_image_src() 函数来获取自定义尺寸的图片信息了:

$custom_image = wp_get_attachment_image_src( $attachment_id, 'my-custom-size' );

8. 常见问题解答

  • 为什么 wp_get_attachment_image_src() 返回 false

    • $attachment_id 不是一个有效的附件 ID。
    • 附件的元数据丢失了。
    • 请求的尺寸不存在。
  • 如何获取原始图片的 URL?

    使用 $size = 'full'

  • 如何获取自定义尺寸的图片 URL?

    先使用 add_image_size() 函数注册自定义尺寸,然后使用 wp_get_attachment_image_src() 函数获取。

  • 如何重新生成缩略图?

    可以使用 Regenerate Thumbnails 插件。

9. 总结

wp_get_attachment_image_src() 函数是 WordPress 中一个非常实用的函数,它可以帮助我们轻松地获取附件图片的 URL、宽度和高度。 理解它的工作原理,可以让我们更好地使用它,并解决一些常见的问题。

希望今天的讲解对大家有所帮助! 记住,源码是最好的老师,多看源码,多思考,你也能成为 WordPress 大神!

下次再见!

发表回复

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