剖析 WordPress `wp_get_attachment_image()` 函数在 WP-CLI 中的源码:如何在命令行中获取附件信息。

大家好,我是你们今天的WordPress附件信息命令行探险导游。 准备好,我们要深入 wp_get_attachment_image() 的源码腹地,并学习如何用 WP-CLI 驯服这些附件,让它们乖乖地在命令行里吐出信息!

第一站:wp_get_attachment_image() 的解剖室

首先,让我们简单回顾一下 wp_get_attachment_image() 这个函数。 它藏在 WordPress 的 wp-includes/post-template.php 文件里。 它的主要任务是生成一个 HTML <img> 标签,用于显示附件(通常是图片)。 它的基本用法是:

<?php
$image = wp_get_attachment_image( $attachment_id, $size, $icon, $attr );
echo $image;
?>
  • $attachment_id: 附件的 ID (post ID)。 它是必须提供的参数。
  • $size: 图片尺寸 (thumbnail, medium, large, full, 或自定义尺寸)。 默认为 "thumbnail"。
  • $icon: 是否为图标,仅当附件类型为图标时使用 (例如,PDF 文档)。 默认为 false。
  • $attr: 一个关联数组,包含要添加到 <img> 标签的属性 (例如,alt, title, class)。

现在,让我们看看这个函数的核心部分(简化版):

function wp_get_attachment_image( $attachment_id = 0, $size = 'thumbnail', $icon = false, $attr = '' ) {
    $attachment_id = intval( $attachment_id );
    if ( ! is_int( $attachment_id ) || $attachment_id < 1 ) {
        return false;
    }

    $image = '';
    $atts = array();

    $image_src = wp_get_attachment_image_src( $attachment_id, $size, $icon );
    if ( $image_src ) {
        list( $src, $width, $height ) = $image_src;
        $hwstring = image_hwstring( $width, $height );

        $default_attr = array(
            'src'   => $src,
            'class' => "attachment-$size size-$size",
            'alt'   => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
        );
        $attr = wp_parse_args( $attr, $default_attr );
        $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment_id, $size );

        $attr_string = '';
        foreach ( $attr as $key => $value ) {
            $attr_string .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
        }

        $image = sprintf( '<img src="%s" %s %s />', esc_url( $src ), $hwstring, $attr_string );
    }

    $image = apply_filters( 'wp_get_attachment_image', $image, $attachment_id, $size, $icon, $attr );

    if ( ! empty( $image ) ) {
      return $image;
    }
    return false;
}

关键点:

  • wp_get_attachment_image_src(): 这个函数才是真正的核心。 它返回一个数组,包含图片的 URL、宽度和高度。 我们等会儿会更详细地分析它。
  • image_hwstring(): 生成 heightwidth 属性的字符串。
  • get_post_meta(): 获取附件的 alt 文本。 _wp_attachment_image_alt 是存储 alt 文本的 meta key。
  • wp_parse_args(): 合并默认属性和用户提供的属性。
  • apply_filters(): 允许通过过滤器修改属性和最终的 HTML。

第二站:wp_get_attachment_image_src() 的秘密基地

现在,让我们深入 wp_get_attachment_image_src() 函数。 这个函数位于同一个文件 (wp-includes/post-template.php)。 它的作用是根据给定的附件 ID 和尺寸,获取图片的 URL、宽度和高度。

function wp_get_attachment_image_src( $attachment_id = 0, $size = 'thumbnail', $icon = false ) {
    $attachment_id = intval( $attachment_id );
    if ( ! is_int( $attachment_id ) || $attachment_id < 1 ) {
        return false;
    }

    $size = $size ? $size : 'thumbnail';

    $image = false;
    $resized = false;

    if ( $icon && wp_attachment_is_image( $attachment_id ) ) {
        $file = wp_mime_type_icon( $attachment_id );
        if ( $file && file_exists( $file ) ) {
            $image = array(
                wp_get_attachment_url( $attachment_id ),
                0,
                0,
                true,
            );
        }
    }

    if ( ! $image ) {
        $image = wp_get_attachment_metadata( $attachment_id );

        if ( is_array( $image ) ) {
            if ( isset( $image['sizes'] ) && isset( $image['sizes'][ $size ] ) ) {
                $src = $image['sizes'][ $size ]['file'];
                $width = $image['sizes'][ $size ]['width'];
                $height = $image['sizes'][ $size ]['height'];
                $resized = true;
            } elseif ( $size == 'full' ) {
                $src = $image['file'];
                $width = $image['width'];
                $height = $image['height'];
            }

            if ( $resized || $size == 'full' ) {
                if ( preg_match( '/^[a-z]+:///', $src ) ) {
                    $url = $src;
                } else {
                    $url = wp_get_attachment_url( $attachment_id );
                    $url = path_join( dirname( $url ), $src );
                }

                if ( $url ) {
                    $image = array(
                        $url,
                        $width,
                        $height,
                        $resized,
                    );
                }
            }
        }
    }

    if ( ! is_array( $image ) ) {
        return false;
    }

    return apply_filters( 'wp_get_attachment_image_src', $image, $attachment_id, $size );
}

关键点:

  • wp_get_attachment_metadata(): 这是获取附件信息的关键函数! 它返回一个包含附件元数据的数组,包括不同尺寸的图片信息。
  • $image['sizes']: 这个数组包含了各种尺寸的图片信息,例如 thumbnail, medium, large 等。 每个尺寸都有 file (文件名), width, height 属性。
  • wp_get_attachment_url(): 获取附件的完整 URL。
  • apply_filters(): 允许通过过滤器修改最终的图片信息。

第三站:WP-CLI 的登陆点

现在,我们开始构建我们的 WP-CLI 命令。 首先,我们需要创建一个自定义的 WP-CLI 命令类。 假设我们想创建一个名为 attachment 的命令,它有一个子命令 info,用于获取附件的信息。

  1. 创建命令类文件: 在你的 WordPress 插件目录中,创建一个名为 class-wp-cli-attachment-command.php 的文件。

  2. 定义命令类:

<?php

if ( ! class_exists( 'WP_CLI' ) ) {
    return;
}

/**
 * Manage attachments.
 */
class WP_CLI_Attachment_Command {

    /**
     * Gets information about an attachment.
     *
     * ## OPTIONS
     *
     * <attachment_id>
     * : The ID of the attachment.
     *
     * [--size=<size>]
     * : The size of the image to get information for.
     * ---
     * default: full
     * options:
     *   thumbnail
     *   medium
     *   large
     *   full
     * ---
     *
     * ## EXAMPLES
     *
     *     wp attachment info 123
     *     wp attachment info 123 --size=thumbnail
     *
     * @param array $args       Positional arguments.
     * @param array $assoc_args Associative arguments.
     */
    public function info( $args, $assoc_args ) {
        $attachment_id = $args[0];
        $size = isset( $assoc_args['size'] ) ? $assoc_args['size'] : 'full';

        $image_data = wp_get_attachment_image_src( $attachment_id, $size );

        if ( ! $image_data ) {
            WP_CLI::error( "Could not find attachment with ID $attachment_id or size '$size'." );
            return;
        }

        WP_CLI::line( WP_CLI::colorize( "%YAttachment ID:%n " . $attachment_id ) );
        WP_CLI::line( WP_CLI::colorize( "%YSize:%n " . $size ) );
        WP_CLI::line( WP_CLI::colorize( "%YURL:%n " . $image_data[0] ) );
        WP_CLI::line( WP_CLI::colorize( "%YWidth:%n " . $image_data[1] ) );
        WP_CLI::line( WP_CLI::colorize( "%YHeight:%n " . $image_data[2] ) );
        WP_CLI::line( WP_CLI::colorize( "%YResized:%n " . ( $image_data[3] ? 'Yes' : 'No' ) ) );
    }
}

WP_CLI::add_command( 'attachment', 'WP_CLI_Attachment_Command' );

关键点:

  • WP_CLI::add_command(): 将我们的命令类注册到 WP-CLI。
  • info() 方法: 这是我们的子命令的入口点。 它接收两个参数:
    • $args: 位置参数 (例如,附件 ID)。
    • $assoc_args: 关联参数 (例如,--size=thumbnail)。
  • WP_CLI::error(): 显示错误消息。
  • WP_CLI::line(): 输出普通文本。
  • WP_CLI::colorize(): 输出带颜色的文本,提高可读性。
  1. 激活插件: 确保你的插件已激活,以便 WP-CLI 能够找到并加载你的命令类。

第四站:命令行测试

现在,让我们尝试运行我们的命令。

  1. 打开终端并导航到你的 WordPress 根目录。

  2. 运行以下命令:

    wp attachment info 123

    (将 123 替换为实际的附件 ID)

    你应该看到类似以下的输出:

    Attachment ID: 123
    Size: full
    URL: http://example.com/wp-content/uploads/2023/10/my-image.jpg
    Width: 1024
    Height: 768
    Resized: No
  3. 尝试使用不同的尺寸:

    wp attachment info 123 --size=thumbnail

    输出会显示缩略图的 URL、宽度和高度。

第五站:更高级的技巧

  • 获取所有附件的 ID: 你可以使用 WP_Query 来获取所有附件的 ID,然后循环遍历它们。

    $query = new WP_Query( array(
        'post_type'      => 'attachment',
        'post_status'    => 'any',
        'posts_per_page' => -1,
        'fields'         => 'ids', // 只获取 ID
    ) );
    
    $attachment_ids = $query->posts;
    
    if ( ! empty( $attachment_ids ) ) {
        foreach ( $attachment_ids as $attachment_id ) {
            // 在这里处理每个附件 ID
            WP_CLI::line( "Attachment ID: " . $attachment_id );
        }
    } else {
        WP_CLI::line( "No attachments found." );
    }

    将这段代码添加到你的命令类中,可以遍历所有附件。

  • 输出为 JSON 或 YAML: WP-CLI 支持将数据输出为 JSON 或 YAML 格式,方便你在脚本中使用。

    $data = array(
        'attachment_id' => $attachment_id,
        'size'          => $size,
        'url'           => $image_data[0],
        'width'         => $image_data[1],
        'height'        => $image_data[2],
        'resized'       => $image_data[3],
    );
    
    WP_CLI::line( json_encode( $data ) ); // 输出为 JSON
    // 或者
    WP_CLI::line( SymfonyComponentYamlYaml::dump( $data ) ); // 输出为 YAML (需要安装 Symfony Yaml 组件)

    要使用 YAML 输出,你需要先安装 Symfony Yaml 组件:

    composer require symfony/yaml

    然后,在你的插件文件中包含 Composer 的 autoloader:

    require_once __DIR__ . '/vendor/autoload.php';

    现在,你可以使用 --format=json--format=yaml 选项来控制输出格式:

    wp attachment info 123 --format=json
    wp attachment info 123 --format=yaml
  • 自定义输出字段: 你可以添加 --field=<field>--fields=<fields> 选项来选择要输出的字段。

    /**
     * Gets information about an attachment.
     *
     * ## OPTIONS
     *
     * <attachment_id>
     * : The ID of the attachment.
     *
     * [--size=<size>]
     * : The size of the image to get information for.
     * ---
     * default: full
     * options:
     *   thumbnail
     *   medium
     *   large
     *   full
     * ---
     *
     * [--field=<field>]
     * : Prints the value of a single field.
     *
     * [--fields=<fields>]
     * : Limits the output to specific fields. Defaults to all fields.
     *
     * ## EXAMPLES
     *
     *     wp attachment info 123 --field=url
     *     wp attachment info 123 --fields=url,width,height
     *
     * @param array $args       Positional arguments.
     * @param array $assoc_args Associative arguments.
     */
    public function info( $args, $assoc_args ) {
        $attachment_id = $args[0];
        $size = isset( $assoc_args['size'] ) ? $assoc_args['size'] : 'full';
    
        $image_data = wp_get_attachment_image_src( $attachment_id, $size );
    
        if ( ! $image_data ) {
            WP_CLI::error( "Could not find attachment with ID $attachment_id or size '$size'." );
            return;
        }
    
        $data = array(
            'attachment_id' => $attachment_id,
            'size'          => $size,
            'url'           => $image_data[0],
            'width'         => $image_data[1],
            'height'        => $image_data[2],
            'resized'       => $image_data[3] ? 'Yes' : 'No',
        );
    
        if ( isset( $assoc_args['field'] ) ) {
            if ( ! isset( $data[ $assoc_args['field'] ] ) ) {
                WP_CLI::error( "Field '{$assoc_args['field']}' not found." );
                return;
            }
            WP_CLI::line( $data[ $assoc_args['field'] ] );
        } elseif ( isset( $assoc_args['fields'] ) ) {
            $fields = explode( ',', $assoc_args['fields'] );
            $output = array();
            foreach ( $fields as $field ) {
                $field = trim( $field );
                if ( ! isset( $data[ $field ] ) ) {
                    WP_CLI::error( "Field '{$field}' not found." );
                    return;
                }
                $output[ $field ] = $data[ $field ];
            }
            WP_CLI::print_table( array( $output ), array_keys( $output ) );
        } else {
            WP_CLI::line( WP_CLI::colorize( "%YAttachment ID:%n " . $data['attachment_id'] ) );
            WP_CLI::line( WP_CLI::colorize( "%YSize:%n " . $data['size'] ) );
            WP_CLI::line( WP_CLI::colorize( "%YURL:%n " . $data['url'] ) );
            WP_CLI::line( WP_CLI::colorize( "%YWidth:%n " . $data['width'] ) );
            WP_CLI::line( WP_CLI::colorize( "%YHeight:%n " . $data['height'] ) );
            WP_CLI::line( WP_CLI::colorize( "%YResized:%n " . $data['resized'] ) );
        }
    }

    现在你可以使用以下命令:

    wp attachment info 123 --field=url
    wp attachment info 123 --fields=url,width,height

    --field 选项会输出单个字段的值,而 --fields 选项会输出一个包含指定字段的表格。

第六站:注意事项

  • 错误处理: 确保你的代码包含适当的错误处理,例如检查附件 ID 是否有效,以及文件是否存在。
  • 性能: 对于大量附件,使用 WP_Querywp_get_attachment_metadata() 可能会影响性能。 考虑使用缓存或批量处理来提高效率。
  • 安全: 始终对用户输入进行验证和转义,以防止安全漏洞。

总结

通过解剖 wp_get_attachment_image()wp_get_attachment_image_src() 函数,我们了解了如何获取附件的信息。 结合 WP-CLI,我们可以轻松地在命令行中访问这些信息,并将其用于各种自动化任务。 希望这次探险对你有所帮助! 现在,拿起你的 WP-CLI,开始探索 WordPress 附件的奇妙世界吧!

发表回复

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