各位听众朋友们,大家好!今天老衲就来跟大家聊聊 WordPress 里那个负责把图片区块变漂亮的小家伙——gutenberg_render_block_core_image()
函数。这玩意儿藏在 WordPress 的核心代码里,专门负责把古腾堡编辑器里的图片区块渲染成咱们在网页上看到的实际图片。
咱们的目标是扒开它的源码,看看它到底做了些什么,怎么把各种图片属性,比如大小、对齐方式、链接等等,都巧妙地塞到 HTML 代码里去的。准备好了吗?咱们这就开始!
一、找到目标,锁定函数
首先,我们要找到这个gutenberg_render_block_core_image()
函数。它藏身于 WordPress 核心代码的 wp-includes/blocks/image.php
文件里。打开这个文件,找到这个函数,我们就锁定了今天的目标。
二、代码剖析,逐行解读
接下来,咱们就要像解剖青蛙一样,把这个函数的源码一行一行地剖析开来,看看它到底有哪些组成部分。
<?php
/**
* Registers the core/image block.
*
* @since 5.0.0
*/
function register_block_core_image() {
register_block_type_from_metadata(
__DIR__ . '/image',
array(
'render_callback' => 'gutenberg_render_block_core_image',
)
);
}
add_action( 'init', 'register_block_core_image' );
/**
* Renders the `core/image` block on the server.
*
* @param array $attributes The block attributes.
* @param string $content The block default content.
* @param WP_Block $block The block instance.
* @return string The rendered HTML.
*/
function gutenberg_render_block_core_image( $attributes, $content, $block ) {
static $block_index = 0;
$block_index++;
$default_size = 'medium';
if ( isset( $attributes['sizeSlug'] ) ) {
$default_size = $attributes['sizeSlug'];
}
$args = array(
'class' => 'wp-block-image',
);
if ( isset( $attributes['align'] ) ) {
$args['class'] .= ' align' . $attributes['align'];
}
if ( isset( $attributes['className'] ) ) {
$args['class'] .= ' ' . $attributes['className'];
}
$image = null;
if ( isset( $attributes['id'] ) ) {
$image = wp_get_attachment_image(
$attributes['id'],
isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : $default_size,
false,
array(
'class' => 'wp-image-' . $attributes['id'],
)
);
}
$image_style = '';
if ( isset( $attributes['width'] ) ) {
$image_style .= 'width:' . $attributes['width'] . 'px;';
}
if ( isset( $attributes['height'] ) ) {
$image_style .= 'height:' . $attributes['height'] . 'px;';
}
if ( ! empty( $image_style ) ) {
$args['style'] = $image_style;
}
$link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none';
$link_target = isset( $attributes['linkTarget'] ) && $attributes['linkTarget'] === '_blank';
$link_rel = isset( $attributes['rel'] ) ? 'rel="' . esc_attr( $attributes['rel'] ) . '"' : '';
$custom_url = isset( $attributes['href'] ) ? $attributes['href'] : '';
$figure_content = '';
if ( ! empty( $image ) ) {
$figure_content = $image;
} elseif ( isset( $attributes['url'] ) ) {
$alt_text = isset( $attributes['alt'] ) ? esc_attr( $attributes['alt'] ) : '';
$figure_content = sprintf(
'<img src="%1$s" alt="%2$s"%3$s />',
esc_url( $attributes['url'] ),
$alt_text,
! empty( $image_style ) ? ' style="' . esc_attr( $image_style ) . '"' : ''
);
}
if ( 'none' !== $link_destination ) {
$url = '';
if ( 'custom' === $link_destination && ! empty( $custom_url ) ) {
$url = $custom_url;
} elseif ( isset( $attributes['id'] ) ) {
if ( 'media' === $link_destination || 'attachment' === $link_destination ) {
$url = wp_get_attachment_url( $attributes['id'] );
}
}
if ( ! empty( $url ) ) {
$figure_content = sprintf(
'<a href="%1$s"%2$s%3$s>%4$s</a>',
esc_url( $url ),
$link_target ? ' target="_blank"' : '',
$link_rel,
$figure_content
);
}
}
$caption = '';
if ( ! empty( $attributes['caption'] ) ) {
$caption = sprintf(
'<figcaption class="wp-element-caption">%1$s</figcaption>',
wp_kses_post( $attributes['caption'] )
);
}
$html = sprintf(
'<figure%1$s>%2$s%3$s</figure>',
empty( $args['class'] ) ? '' : ' class="' . esc_attr( $args['class'] ) . '"',
$figure_content,
$caption
);
return $html;
}
三、流程拆解,各个击破
咱们把整个函数拆解成几个关键步骤,逐个分析:
-
初始化和默认值:
static $block_index = 0; $block_index++; $default_size = 'medium'; if ( isset( $attributes['sizeSlug'] ) ) { $default_size = $attributes['sizeSlug']; }
static $block_index = 0; $block_index++;
这两行代码主要是为了跟踪区块的渲染次数,虽然在这个函数里用处不大,但可能在调试或者某些特定场景下有用。$default_size = 'medium';
设置默认的图片尺寸为medium
。if ( isset( $attributes['sizeSlug'] ) ) { $default_size = $attributes['sizeSlug']; }
如果区块属性中指定了sizeSlug
(比如thumbnail
、large
等),就用指定的尺寸。
-
处理类名:
$args = array( 'class' => 'wp-block-image', ); if ( isset( $attributes['align'] ) ) { $args['class'] .= ' align' . $attributes['align']; } if ( isset( $attributes['className'] ) ) { $args['class'] .= ' ' . $attributes['className']; }
$args['class'] = 'wp-block-image';
设置基本的类名wp-block-image
。if ( isset( $attributes['align'] ) ) { $args['class'] .= ' align' . $attributes['align']; }
如果区块属性中有align
属性(比如left
、center
、right
),就添加相应的对齐类名。if ( isset( $attributes['className'] ) ) { $args['class'] .= ' ' . $attributes['className']; }
如果区块属性中有className
属性,就添加自定义的类名。
-
获取图片:
$image = null; if ( isset( $attributes['id'] ) ) { $image = wp_get_attachment_image( $attributes['id'], isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : $default_size, false, array( 'class' => 'wp-image-' . $attributes['id'], ) ); }
$image = null;
初始化$image
变量。if ( isset( $attributes['id'] ) ) { ... }
如果区块属性中有id
属性(也就是图片附件的 ID),就使用wp_get_attachment_image()
函数来获取图片 HTML 代码。wp_get_attachment_image()
函数会根据id
、sizeSlug
和其他参数生成<img>
标签。- 这里还添加了一个类名
wp-image-
+ 图片ID,方便 CSS 定制。
-
处理图片样式:
$image_style = ''; if ( isset( $attributes['width'] ) ) { $image_style .= 'width:' . $attributes['width'] . 'px;'; } if ( isset( $attributes['height'] ) ) { $image_style .= 'height:' . $attributes['height'] . 'px;'; } if ( ! empty( $image_style ) ) { $args['style'] = $image_style; }
$image_style = '';
初始化$image_style
变量。- 如果区块属性中有
width
和height
属性,就将它们添加到$image_style
变量中,形成 CSS 样式。 - 最后,如果
$image_style
不为空,就将它添加到$args
数组中。
-
处理链接:
$link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; $link_target = isset( $attributes['linkTarget'] ) && $attributes['linkTarget'] === '_blank'; $link_rel = isset( $attributes['rel'] ) ? 'rel="' . esc_attr( $attributes['rel'] ) . '"' : ''; $custom_url = isset( $attributes['href'] ) ? $attributes['href'] : ''; $figure_content = ''; if ( ! empty( $image ) ) { $figure_content = $image; } elseif ( isset( $attributes['url'] ) ) { $alt_text = isset( $attributes['alt'] ) ? esc_attr( $attributes['alt'] ) : ''; $figure_content = sprintf( '<img src="%1$s" alt="%2$s"%3$s />', esc_url( $attributes['url'] ), $alt_text, ! empty( $image_style ) ? ' style="' . esc_attr( $image_style ) . '"' : '' ); } if ( 'none' !== $link_destination ) { $url = ''; if ( 'custom' === $link_destination && ! empty( $custom_url ) ) { $url = $custom_url; } elseif ( isset( $attributes['id'] ) ) { if ( 'media' === $link_destination || 'attachment' === $link_destination ) { $url = wp_get_attachment_url( $attributes['id'] ); } } if ( ! empty( $url ) ) { $figure_content = sprintf( '<a href="%1$s"%2$s%3$s>%4$s</a>', esc_url( $url ), $link_target ? ' target="_blank"' : '', $link_rel, $figure_content ); } }
$link_destination
决定链接的目标,可以是none
(无链接)、media
(链接到媒体文件)、attachment
(链接到附件页面)或custom
(自定义链接)。$link_target
决定是否在新标签页打开链接。$link_rel
设置链接的rel
属性,比如noopener
、noreferrer
等。$custom_url
是自定义链接的 URL。- 这段代码首先判断是否有图片,如果有,就将
$image
赋值给$figure_content
。如果没有,但有 URL,就创建一个<img>
标签,并将它赋值给$figure_content
。 - 然后,根据
$link_destination
的值,决定是否将$figure_content
包裹在一个<a>
标签中。
-
处理图片描述:
$caption = ''; if ( ! empty( $attributes['caption'] ) ) { $caption = sprintf( '<figcaption class="wp-element-caption">%1$s</figcaption>', wp_kses_post( $attributes['caption'] ) ); }
- 如果区块属性中有
caption
属性,就创建一个<figcaption>
标签,并将caption
的值包裹在其中。wp_kses_post()
函数用于对caption
进行安全过滤。
- 如果区块属性中有
-
生成最终 HTML:
$html = sprintf( '<figure%1$s>%2$s%3$s</figure>', empty( $args['class'] ) ? '' : ' class="' . esc_attr( $args['class'] ) . '"', $figure_content, $caption ); return $html;
- 使用
sprintf()
函数将所有的元素组合成一个<figure>
标签,并返回最终的 HTML 代码。
- 使用
四、属性解读,抽丝剥茧
现在,咱们来详细分析一下这个函数用到的各种属性:
属性名 | 类型 | 描述 |
---|---|---|
id |
integer | 图片附件的 ID。 |
url |
string | 图片的 URL。如果 id 存在,则优先使用 id 获取图片,否则使用 url 。 |
alt |
string | 图片的 alt 属性。 |
caption |
string | 图片的描述文字。 |
align |
string | 图片的对齐方式,可以是 left 、center 、right 或 wide 、full 。 |
width |
integer | 图片的宽度,单位是像素。 |
height |
integer | 图片的高度,单位是像素。 |
linkDestination |
string | 链接的目标,可以是 none (无链接)、media (链接到媒体文件)、attachment (链接到附件页面)或 custom (自定义链接)。 |
linkTarget |
boolean | 是否在新标签页打开链接,true 表示在新标签页打开,false 表示在当前标签页打开。 |
href |
string | 自定义链接的 URL。 |
rel |
string | 链接的 rel 属性,比如 noopener 、noreferrer 等。 |
sizeSlug |
string | 图片的尺寸,可以是 thumbnail 、medium 、large 或 full 。 |
className |
string | 自定义的 CSS 类名。 |
五、实战演练,举例说明
为了更好地理解这个函数,咱们来举个例子。假设咱们在古腾堡编辑器里插入了一个图片区块,并设置了以下属性:
id
= 123alt
= "这是一张美丽的风景图片"caption
= "美丽的风景"align
= "center"linkDestination
= "media"
那么,gutenberg_render_block_core_image()
函数会生成类似下面的 HTML 代码:
<figure class="wp-block-image aligncenter">
<a href="http://example.com/wp-content/uploads/2023/10/image.jpg">
<img src="http://example.com/wp-content/uploads/2023/10/image-medium.jpg" alt="这是一张美丽的风景图片" class="wp-image-123" />
</a>
<figcaption class="wp-element-caption">美丽的风景</figcaption>
</figure>
六、总结与升华
通过对 gutenberg_render_block_core_image()
函数的源码分析,咱们可以得出以下结论:
- 这个函数的主要作用是将图片区块的属性转换为 HTML 代码。
- 它使用了
wp_get_attachment_image()
函数来获取图片 HTML 代码。 - 它支持多种图片属性,比如大小、对齐方式、链接等等。
- 它使用了
sprintf()
函数来生成最终的 HTML 代码。
掌握了这个函数的原理,咱们就可以更好地定制图片区块的样式和功能,让网站的图片更加美观和实用。
七、一点小技巧
- 如果你想修改图片区块的默认样式,可以通过 CSS 来覆盖默认的类名。
- 如果你想添加自定义的图片属性,可以通过
block.json
文件来定义新的属性,并在render_callback
函数中处理这些属性。 - 如果你想完全自定义图片区块的 HTML 代码,可以编写自己的
render_callback
函数。
好了,今天的讲座就到这里。希望大家有所收获,咱们下次再见!