社区新闻

介绍区块绑定,第二部分:使用自定义绑定源

如果我说你可以将来自任何源的自定义数据绑定到 WordPress 核心区块,你会怎么想?我想这应该会让你兴奋起来,并激发你的思维火花。

当我第一次听说这可以实现时,我迫不及待地想尝试一下。自从区块编辑器问世以来,我多年来有过很多很棒的想法,但一直无法在系统内很好地实现它们。

WordPress 6.5 将引入区块绑定,这是一个新的 API,将为任何需要动态输出数据而无需编写自定义区块的人打开一个充满可能性的世界。在本文中,你将学习如何注册自己的绑定源,并将你想要的任何数据附加到核心区块(至少在 6.5 版本可能的范围内)。

在过去的几周里,我已经用这个新 API 构建了十几个功能,现在与大家分享如何做到这一点是公平的。

本文是介绍区块绑定,第一部分:连接自定义字段的后续文章。建议你先阅读那篇文章,以从基础层面理解区块绑定 API 的工作原理。

自定义区块绑定源概述

正如你在本系列前一篇文章中学到的,区块绑定 API 是用于将属性绑定到任何类型源的机制。WordPress 6.5 将内置两个绑定源:

  • core/post-meta 用于绑定自定义字段的源。
  • core/pattern-overrides 用于处理模式覆盖的源,这是 WordPress 6.5 的另一项功能。 已推迟到 WordPress 6.6。

对于扩展者来说,core/post-meta 源显然是许多项目所需要的。但在许多场景中,你可能需要绑定来自完全不同源的数据。一些想到的想法包括:

  • 分类法术语和用户数据
  • WordPress 站点数据
  • 插件/主题选项
  • 自定义数据库表
  • 第三方 API

有计划在未来的版本中发布 core/site-datacore/user-data 和其他用于处理核心数据的绑定源,但你当然可以在此期间开始自己构建它们。

在区块层面,自定义绑定源的工作方式与 core/post-meta 源完全相同。最大的区别在于,当你注册自定义源时,你可以完全控制绑定在底层的工作方式。并且你必须使用区块绑定 API 来注册你的源。

正如本系列第一篇文章所讨论的,在 WordPress 6.5 中,绑定仅限于图像、段落、标题和按钮区块。预计在未来的版本中会提供更广泛的支持。

了解 API 函数

WordPress 6.5 提供了一个新的 register_block_bindings_source() 函数,用于注册自定义绑定源。它也在内部用于注册自定义字段和未来的模式覆盖源。

看一下函数签名:

register_block_bindings_source(
	string $source_name,
	array $source_properties
);

你可以设置两个参数:

  • $source_name 你的自定义绑定源的唯一名称,格式为 namespace/slug
  • $source_properties 用于定义绑定源的属性数组:
    • label 一个国际化文本字符串,用于表示绑定源。注意:目前未在 UI 中的任何地方显示。
    • get_value_callback 一个 PHP 可调用对象(函数、闭包等),当区块的属性与 $source_name 参数匹配时被调用。
    • uses_context (可选) 如果需要,使用上下文数组扩展区块实例。例如,如果你需要当前文章 ID,可以将其设置为 [ 'postId' ]

注册自定义源时,你需要在 init 钩子上进行。让我们看一个示例(我们将在下一节中看到一个真实的例子):

add_action( 'init', 'projectslug_register_block_bindings' );

function projectslug_register_block_bindings() {
	register_block_bindings_source( 'projectslug/example-source', array(
		'label'              => __( 'My Custom Bindings', 'projectslug' ),
		'get_value_callback' => 'projectslug_bindings_callback',
		'uses_context'       => [ 'postId', 'postType' ]
	) );
}

这就是向 WordPress 注册绑定源所需的全部代码。

当 WordPress 在解析区块时遇到你的 projectslug/example-source 绑定源时,它将运行你的回调函数。你的函数签名应如下所示:

projectslug_bindings_callback(
	array $source_args,
	WP_Block $block_instance,
	string $attribute_name
);

它最多可以接受三个参数,但如果不需要,你不必定义每一个:

  • $source_args 通过区块的 metadata.bindings.$attribute.args 属性传递的参数数组。
  • $block_instance 绑定所连接的区块的当前实例,作为 WP_Block 对象。
  • $attribute_name 通过区块上的 metadata.bindings.$attribute 属性设置的当前属性。

为了将所有这些放在适当的上下文中,让我们跳入一些真实的例子。

决策:定义自定义绑定的结构

你已经在系列第一部分学习了绑定的基础知识。因为自定义绑定非常相似,让我们再提升一个档次,构建一些稍微高级的东西。但不要太担心复杂性——我们仍然只是介绍区块绑定 API 可能性的基础知识。

假设你想构建一个展示用户卡片的区块。也许这是为了公司的团队简介或类似的东西。根据用户卡片需求的复杂程度,你可能根本不需要自定义区块。你可以通过将用户数据绑定到核心区块来构建它。

以下是我们将在接下来的部分中构建的内容的屏幕截图:

一个包含用户头像和简介描述的用户卡片截图。

在屏幕截图中,有三个包含动态数据的区块:

  • 用户显示名称: 绑定到标题区块的内容
  • 头像: 绑定到图像区块的 URL
  • 简介/描述: 绑定到段落区块的内容

预先知道你需要什么类型的数据是决定自定义绑定源如何工作的关键部分。因为这是用户数据,所以你知道你需要用户 ID。你还需要单独访问这些用户数据字段,因此你需要一个参数来指定它们。

这意味着你的绑定源的结构应该期望两个参数:

  • userId 用于确定获取哪个用户的数据
  • key 用于绑定单个用户数据字段

这些参数名称可以是任何你想要的。我决定使用它们是因为它们对我来说最有意义,但你应该使用最适合你项目的名称。

以下是我们稍后在编辑器中使用时 bindings 结构的样子:

{
	"bindings":{
		"attribute_name":{
			"source":"projectslug/user-data",
			"args": {
				"userId":1,
				"key":"a_user_data_field"
			}
		}
	}
}

请不要跳过决定如何构建你接受的参数这一步。这是为了避免日后管理上的麻烦。

注册自定义绑定源

确定了预期的参数后,是时候实际编写处理自定义绑定源的代码了。

你将使用 register_block_bindings_source() 函数注册一个新的 projectslug/user-data 源。将此代码添加到自定义插件文件或主题的 functions.php 中:

add_action( 'init', 'projectslug_register_block_bindings' );

function projectslug_register_block_bindings() {
	register_block_bindings_source( 'projectslug/user-data', array(
		'label'              => __( 'User Data', 'projectslug' ),
		'get_value_callback' => 'projectslug_user_data_bindings'
	) );
}

请注意,在此示例中我们没有定义 uses_context 数组,因为绑定源不依赖于上下文。

现在,在同一文件中定义你的回调函数:

function projectslug_user_data_bindings( $source_args ) {
	// 如果未设置 key 或 userId 参数,则提前退出。
	if ( ! isset( $source_args['key'] ) || ! isset( $source_args['userId'] ) ) {
		return null;
	}

	// 获取用户 ID。
	$user_id = absint( $source_args['userId'] );

	// 如果根本没有用户 ID,则返回 null。
	if ( 0 >= $user_id ) {
		return null;
	}

	// 根据 key 参数返回数据。
	switch ( $source_args['key'] ) {
		case 'name':
			return esc_html( get_the_author_meta( 'display_name', $user_id ) );
		case 'description':
			return get_the_author_meta( 'description', $user_id );
		case 'avatar':
			return esc_url( get_avatar_url( $user_id ) );
		default:
			return null;
	}
}

这个函数做了几件事:

  • 它首先检查是否传入了 key 参数。
  • 然后通过 userId 参数检查用户 ID。
  • 最后,它将 key 值与绑定源支持的一组预定义情况(namedescriptionavatar)进行比较。

如果你为具有富文本类型的属性返回数据,则可能不需要转义它。区块绑定 API 将在内容渲染前通过 wp_kses_post() 传递源值。例如,在上面的代码中,用户描述可能包含富文本,因此我们让 WordPress 处理它并保留 HTML 标签。

最重要的是,该函数返回某种类型的数据。这应该是基于参数的值,如果未找到任何内容,则返回 null

使用自定义绑定源

对于区块代码,我将保持非常简单,使用一个包含嵌套标题、图像和段落区块的组区块。请随意尝试布局。

在 WordPress 管理后台打开一篇新文章或页面。然后,将此区块标记复制并粘贴到代码编辑器中:

<!-- wp:group {"style":{"spacing":{"blockGap":"1rem"}},"layout":{"type":"default"}} -->
<div class="wp-block-group">
	<!-- wp:heading {
		"level":3,
		"metadata":{
			"bindings":{
				"content":{
					"source":"projectslug/user-data",
					"args":{
						"userId":1,
						"key":"name"
					}
				}
			}
		}
	} -->
	<h3 class="wp-block-heading"></h3>
	<!-- /wp:heading -->

	<!-- wp:image {
		"width":"96px",
		"height":"96px",
		"scale":"cover",
		"metadata":{
			"bindings":{
				"url":{
					"source":"projectslug/user-data",
					"args":{
						"userId":1,
						"key":"avatar"
					}
				}
			}
		},
		"align":"left",
		"style":{"layout":{"selfStretch":"fit","flexSize":null}}
	} -->
	<figure class="wp-block-image alignleft is-resized">
		<img src="" alt="" style="object-fit:cover;width:96px;height:96px"/>
	</figure>
	<!-- /wp:image -->
	
	<!-- wp:paragraph {
		"metadata":{
			"bindings":{
				"content":{
					"source":"projectslug/user-data",
					"args":{
						"userId":1,
						"key":"description"
					}
				}
			}
		}
	} -->
	<p></p>
	<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->

如果你切换回可视化编辑器,你的输出应该如下所示:

WordPress 文章编辑器,内容区域包含标题、头像和段落区块。标题块有紫色轮廓和工具栏中表示绑定的紫色图标。

被绑定的区块在选中时会显示紫色轮廓,并在工具栏中有一个指示器。从长远来看,WordPress 将开放编辑器端 API 以自定义默认输出。

趣味示例

区块绑定 API 不仅仅是另一项功能。它象征着全球 WordPress 开发者的希望和热情。考虑到这一点,让我们通过将 Hello Dolly 插件连接到核心区块来玩点有趣的!

如果你还没有安装并激活 Hello Dolly 插件——就像任何真正的 WordPress 爱好者一样——现在就去做吧。

打开你的插件文件或主题的 functions.php 文件,并在现有的 projectslug_register_block_bindings() 函数中添加以下内容:

register_block_bindings_source( 'projectslug/fun-stuff', array(
	'label'              => __( 'Fun Stuff', 'projectslug' ),
	'get_value_callback' => 'projectslug_fun_bindings'
));

由于这是与用户数据不同的绑定源,因此注册一个单独的源是有意义的。在这种情况下,它是 projectslug/fun-stuff

现在在同一文件中添加你的源回调函数:

function projectslug_fun_bindings( $source_args ) {
	if ( ! isset( $source_args['key'] )) {
		return null;
	}
	if ( 'hello' === $source_args['key'] && function_exists('hello_dolly_get_lyric')) {
		return esc_html(sprintf(
			// Translators: %s is a lyric from the Hello Dolly plugin.
			__('🎺 🎶 %s', 'projectslug'),
			hello_dolly_get_lyric()
		));
	}
	return null;
}

要测试其工作原理,请从区块编辑器创建一篇新文章、页面或模板。然后打开代码编辑器视图,并将此区块标记粘贴到其中:

<!-- wp:paragraph {
	"metadata":{
		"bindings":{
			"content":{
				"source":"projectslug/fun-stuff",
				"args":{
					"key":"hello"
				}
			}
		}
	}
} -->
<p>Displays a random lyric from the Hello Dolly plugin if installed.</p>
<!-- /wp:paragraph -->

当你切换回可视化编辑器时,你应该看到类似这样的内容:

WordPress 编辑器,内容区域包含演示文本。顶部是一个段落区块,带有高亮的紫色轮廓,告诉用户它将显示来自 Hello Dolly 插件的随机歌词。

正如你所看到的,我们使用了与前面描述的类似技术在编辑器中输出一些默认内容。

现在保存文章并在前端查看它,现在应该显示来自 Hello Dolly 插件的随机歌词:

网站前端的单篇文章,显示演示文本。顶部是来自 Hello Dolly 插件的随机歌词。

当然,你可以使用这种技术来绑定插件和主题的函数输出。我选择这个例子是为了表明,你不一定只考虑从元表中获取数据。目标是——希望如此——让你开始跳出框框思考,并在自己的项目中尝试可能实现的功能。

结论

我说区块绑定 API 象征着 WordPress 开发者的希望,这不仅仅是开玩笑。

我们都听过 WordPress 联合创始人 Matt Mullenweg 关于深入学习 JavaScript 的请求。虽然这在今天仍然非常正确,但我也觉得我们这些喜欢编写 PHP 代码的人又有了一些真正值得兴奋的东西。区块绑定 API 感觉像是回到了我们许多人在经典时代学习的 WordPress。

虽然这仍然是该 API 的“1.0 版本”,但我已经深深爱上了它不仅将在 WordPress 6.5 中,而且在未来几年内提供的可能性。这是很长一段时间以来登陆 WordPress 的最具革命性的开发工具之一。

它将改变我们使用 WordPress 的方式。

资源

在发布时,区块绑定 API 仍在进行一些最后的润色。WordPress 6.5 将只发布该 API 的初始版本,预计在未来的版本中会持续改进。要了解当前和未来的变化,请使用这些资源。