社区新闻

在 WordPress 6.7 中通过插件注册区块模板

查看官方原文 ↗ 发布于

WordPress 6.7 的开发正在推进,该版本最大的功能之一现已登陆 Gutenberg 插件:通过插件实现的区块模板

如果你曾经构建过带有前端模板输出的插件,你就会知道在尝试输出插件生成的内容时,与主题良好协作是多么困难。这在构建自定义文章类型、自定义分类法甚至虚拟页面(即自定义 URL)时尤其常见。十多年来,这一直是一个问题,核心代码库没有提供标准的解决方案。

Gutenberg 19.1(最终将合并到 WordPress 6.7 中)开始,你可以开始为你的插件注册区块模板并定义默认内容。因为这一切都构建在区块系统之上,所以主题和用户都可以自定义模板。

在本教程中,我将引导你了解从插件注册区块模板的基础知识,向你展示如何通过主题覆盖它们,并在此过程中分享一些技巧。

请记住,我们仍处于 WordPress 6.7 的开发周期中。本教程中分享的方法随时可能发生变化。我将在整个发布周期中更新任何变更的信息。

更新: 本文中提到的新函数已更新以移除 wp_ 前缀。Gutenberg 19.5 和 WordPress 6.7 将不包含此前缀。新函数将命名为 register_block_template()unregister_block_template()

要求和设置

要测试此新功能,你的开发环境必须运行以下版本:

  • Gutenberg 19.1+
  • WordPress 6.6+(最好针对主干版本进行测试)

让我们为本教程设置一个测试插件。在你的 WordPress /plugins 目录中创建一个新的 devblog-plugin-templates 文件夹。然后在该文件夹中添加一个 plugin.php 文件,内容如下:

<?php
/**
 * Plugin Name:       Developer Blog: Plugin Templates
 * Description:       Example code for registering plugin block templates with WordPress 6.7+.
 * Version:           1.0.0
 * Requires at least: 6.6
 * Requires PHP:      7.4
 * Requires Plugins:  gutenberg
 * Text Domain:       devblog-plugin-templates
 */

add_action( 'init', 'devblog_register_plugin_templates' );

function devblog_register_plugin_templates() {
	// Add calls to register_block_template() here.
}

激活此插件。

你会注意到代码中有一个 devblog_register_plugin_templates() 函数挂载到 init 钩子上。你将在整个教程中使用它来注册你的区块模板。

模板注册基础

WordPress 6.7 将包含一个 register_block_template() 函数,允许你向站点编辑器添加新模板:

register_block_template( string $template_name, $args = array() )

该函数接受两个参数,用于定义模板的注册方式:

  • $template_name: 模板名称,格式为 plugin_uri//template_name(注意需要双斜杠 //)。plugin_uri 应与你的插件文件夹名称匹配。
  • $args: 定义模板的参数数组:
    • title: 模板的国际化标题。
    • description: 模板的国际化描述。
    • content: 在编辑器或前端渲染时模板的默认内容(区块标记)。
    • post_types: 文章类型 slug 数组,作为每篇文章的自定义模板供用户使用。

截至 Gutenberg 19.1,技术上可以为 $template_name 参数的 plugin_uri 部分使用任何字符串,并且它会在 UI 中显示。但它不会绑定到任何特定的插件。有一个待解决的问题是限制仅允许活跃插件注册。

让我们尝试注册一个名为 Example 的基本模板。将此代码添加到你的 plugin.php 文件中的 devblog_register_plugin_templates() 函数内:

register_block_template( 'devblog-plugin-templates//example', [
	'title'       => __( 'Example', 'devblog-plugin-templates' ),
	'description' => __( 'An example block template from a plugin.', 'devblog-plugin-templates' )
] );

现在转到 WordPress 管理后台的 外观 > 编辑器 > 模板。你应该会看到一个带有你插件名称的全新菜单项(本例中为 Developer Blog: Plugin Templates)。点击后,你将看到刚刚注册的模板:

WordPress 站点编辑器中的模板屏幕。一个插件面板已打开,显示一个空的模板。

你会注意到 WordPress 在这种情况下显示 空模板 文本,因为你尚未为其定义任何内容。

register_block_template() 是一个插件特定的函数,目前不打算在主题内使用。从技术上讲,可以通过在主题的 /templates 文件夹中放置任何模板文件来“注册”自定义模板,但你不能使用 register_block_template() 来添加标题和描述。相反,你需要过滤 default_template_types

注册带内容的模板

让我们更进一步,为模板添加一些默认内容。你可以通过向 content 参数添加一些区块标记来实现。更改你的代码,使其如下所示:

register_block_template( 'devblog-plugin-templates//example', [
	'title'       => __( 'Example', 'devblog-plugin-templates' ),
	'description' => __( 'An example block template from a plugin.', 'devblog-plugin-templates' ),
	'content'     => '
		<!-- wp:template-part {"slug":"header","area":"header","tagName":"header"} /-->
		<!-- wp:group {"tagName":"main"} -->
		<main class="wp-block-group">
			<!-- wp:group {"layout":{"type":"constrained"}} -->
			<div class="wp-block-group">
				<!-- wp:paragraph -->
				<p>This is a plugin-registered template.</p>
				<!-- /wp:paragraph -->
			</div>
			<!-- /wp:group -->
		</main>
		<!-- /wp:group -->
		<!-- wp:template-part {"slug":"footer","area":"footer","tagName":"footer"} /-->'
] );

你会注意到我保持了相对简单,调用了页眉和页脚模板部件、一些包装的 Group 区块和一个 Paragraph 区块。基本标记是从 Twenty Twenty-Four 主题复制的。

一般来说,为你的插件模板复制最新默认主题的任何包装标记是一个好习惯,这将使其与许多其他主题最兼容。这是因为许多主题作者以默认主题为起点。

因为它是区块标记,所以技术上你可以使用任何内容,并且它可以在任何区块主题中正常工作而不会出错。但它可能无法完美适应每个主题的设计。

如果你刷新 模板 屏幕,你应该会在模板预览中看到你的更改:

WordPress 站点编辑器中的模板屏幕。一个插件面板已打开,显示一个带有演示内容的模板。

当然,这个模板可以像任何其他模板一样由用户完全自定义。

专业技巧:更简洁的模板区块标记

我不喜欢将区块标记(HTML)分配给 PHP 函数中的参数。你会在代码编辑器中失去语法高亮等功能,而且这通常只会让原本可读的代码看起来混乱。最好将模板标记添加到单独的文件中。

为了解决这个问题,我创建了一个自定义函数来获取模板文件的内容。我们将在本教程的其余部分使用此函数来保持代码整洁,所以请将其添加到你的 plugin.php 文件中:

function devblog_get_template_content( $template ) {
	ob_start();
	include __DIR__ . "/templates/{$template}";
	return ob_get_clean();
}

你可以使用此函数获取模板文件的内容,并将其分配给 content 参数。

在此之前,创建一个新的 /templates 文件夹,并添加一个包含你的区块标记的 example.php 模板文件:

<!-- wp:template-part {"slug":"header","area":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main"} -->
<main class="wp-block-group">

	<!-- wp:group {"layout":{"type":"constrained"}} -->
	<div class="wp-block-group">

		<!-- wp:paragraph -->
		<p><?php esc_html_e( 'This is a plugin-registered template.', 'devblog-plugin-templates' ); ?></p>
		<!-- /wp:paragraph -->

	</div>
	<!-- /wp:group -->

</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","area":"footer","tagName":"footer"} /-->

现在更新你原始的 register_block_template() 调用,使用这个新函数,从 /templates/example.php 获取区块标记:

register_block_template( 'devblog-plugin-templates//example', [
	'title'       => __( 'Example', 'devblog-plugin-templates' ),
	'description' => __( 'An example block template from a plugin.', 'devblog-plugin-templates' ),
	'content'     => devblog_get_template_content( 'example.php' )
] );

如何注销模板

WordPress 还将引入一个新的 unregister_block_template() 函数,用于——你猜对了——注销区块模板。尝试将这行代码放入你的 devblog_register_plugin_templates() 函数中, 你注册 Example 模板的调用之后:

unregister_block_template( 'devblog-plugin-templates//example' );

该函数接受一个参数 $template_name。此参数必须包含插件 URI 和模板 slug,用双斜杠分隔,就像最初注册时一样。

unregister_block_template() 可用于注销任何插件注册的模板。但它不能用于注销由主题或用户添加的模板。

插件区块模板如何与主题和用户自定义协作

与任何其他区块模板一样,用户可以直接从 WordPress 管理后台的 外观 > 编辑器 > 模板 屏幕编辑它们。这将为他们提供比以往更直接的控制权,并且他们可以使用他们已经熟悉的界面进行自定义。

因为 WordPress 正在引入一种注册模板的标准方法,这意味着插件和主题将能够比以往更容易地集成。即使主题没有专门为你的插件添加模板支持,你仍然可以确保它与任何区块主题兼容。

如果你是区块主题作者,你可以通过创建自己的模板版本来覆盖插件的默认模板内容。你只需将模板添加到主题的 /templates 文件夹中,并包含你想要的任何区块标记。

例如,如果你向主题添加了一个 /templates/example.html 模板,它将在 UI 中你的主题模板列表下显示如下:

WordPress 站点编辑器中的模板屏幕。活动主题的模板以三列网格显示。

一旦模板存在于主题中,它将位于 UI 中的 模板 > 主题名称 面板下,而不再列在原始插件面板下。

你可能还注意到,从主题添加模板时,Example 标题现在显示为模板名称 example,并且描述缺失。有一个拉取请求将在 Gutenberg 19.2 中修复此问题。

注册自定义文章、页面和 CPT 模板

让我们使本教程更有趣,并看一个真实世界的用例,这是你作为 WordPress 开发者在日常生活中可能会遇到的情况。

假设你有一个插件,它注册了一个自定义文章类型,允许用户分享书籍。你需要控制这些书籍在前端如何渲染的默认输出,特别是对于那些没有为插件添加支持的主题。

首先,通过将此代码添加到你的 plugin.php 文件来注册 book 文章类型:

add_action( 'init', 'devblog_register_book_type' );

function devblog_register_book_type() {
	register_post_type( 'book', [
		'public'             => true,
		'show_in_rest'       => true,
		'capability_type'    => 'post',
		'has_archive'        => 'books',
		'menu_icon'          => 'dashicons-book',
		'supports'           => [ 'editor', 'excerpt', 'title', 'thumbnail' ],
		'labels'             => [
			'name'          => __( 'Books',        'devblog-plugin-templates' ),
			'singular_name' => __( 'Book',         'devblog-plugin-templates' ),
			'add_new'       => __( 'Add New Book', 'devblog-plugin-templates' )
		]
	] );
}

这是你的实际书籍文章类型可能看起来的简化版本,但它提供了测试新功能所需的一切。请随时参考 register_post_type() 文档来充实它。

上面的代码将向 WordPress 管理菜单添加一个新的 Books 项。现在添加一些快速演示文章进行测试:

WordPress 管理后台中的 Books 自定义文章类型管理屏幕。它列出了三篇已发布的书籍文章。

在使用自定义文章类型时,理解并运用模板层次结构很重要。通过使用标准的模板 slug,你无需担心进行任何特殊的前端过滤。所有需要做的就是为层次结构中存在的任何模板注册模板本身。

创建单篇文章模板

让我们为你上面注册的书籍文章类型创建一个单篇文章模板。首先,在你的插件文件夹中创建一个空的 /templates/single-book.php 文件。然后向其添加以下区块标记:

<!-- wp:template-part {"slug":"header","area":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main"} -->
<main class="wp-block-group">
	<!-- wp:group {"layout":{"type":"constrained"}} -->
	<div class="wp-block-group">
		<!-- wp:spacer {"height":"var:preset|spacing|50"} -->
		<div style="height:var(--wp--preset--spacing--50)" aria-hidden="true" class="wp-block-spacer"></div>
		<!-- /wp:spacer -->

		<!-- wp:post-title {"textAlign":"center","level":1} /-->

		<!-- wp:spacer {"height":"var:preset|spacing|30","style":{"spacing":{"margin":{"top":"0","bottom":"0"}}}} -->
		<div style="margin-top:0;margin-bottom:0;height:var(--wp--preset--spacing--30)" aria-hidden="true"
			class="wp-block-spacer"></div>
		<!-- /wp:spacer -->

		<!-- wp:post-featured-image {"style":{"spacing":{"margin":{"bottom":"var:preset|spacing|40"}}}} /-->
	</div>
	<!-- /wp:group -->

	<!-- wp:post-content {"lock":{"move":false,"remove":true},"layout":{"type":"constrained"}} /-->
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","area":"footer","tagName":"footer"} /-->

同样,这是使用从 Twenty Twenty-Four 主题复制的基本标记。它显示文章标题、文章特色图像和文章内容区块。请随时调整它并添加任何你想要的区块。

现在像之前一样,在你的 plugin.php 文件的 devblog_register_plugin_templates() 函数中注册模板:

register_block_template( 'devblog-plugin-templates//single-book', [
	'title'       => __( 'Single Book', 'devblog-plugin-templates' ),
	'description' => __( 'Displays a single book.', 'devblog-plugin-templates' ),
	'content'     => devblog_get_template_content( 'single-book.php' )
] );

特别注意使用的 single-book slug。这是 book 文章类型的单篇文章的标准模板名称。使用此 slug 将确保它无需你进一步努力即可工作。

如果你访问管理后台的 外观 > 编辑器 > 模板 屏幕,你将看到新的 Single Book 模板列在插件面板下:

WordPress 站点编辑器中的模板屏幕。它在活动插件面板下列出了两个模板。

像任何其他模板一样,这也可以被主题覆盖或由用户自定义。

创建自定义模板

除了文章类型的普通单篇文章模板外,你还可以创建一个或多个用户可以为单篇文章选择的自定义模板。让我们为 book 文章类型创建一个新的“Book: Canvas”模板,它为用户提供一个开放的画布,仅显示页眉、文章内容和页脚。

将此区块标记添加到你的插件中的一个新文件 /templates/book-canvas.php

<!-- wp:template-part {"slug":"header","area":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","layout":{"type":"default"}} -->
<main class="wp-block-group">

	<!-- wp:post-content {"lock":{"move":false,"remove":true},"layout":{"type":"constrained"}} /-->

</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","area":"footer","tagName":"footer"} /-->

自定义模板没有标准的模板命名约定,因此在这种情况下我选择了 book-canvas。命名时的经验法则是,只要它不是模板层次结构中的保留名称,你可以使用任何名称。

注册自定义模板还引入了 register_block_template()post_types 参数。此参数允许你为一个或多个文章类型注册自定义模板,用户将在编写单篇文章时能够选择此模板。

通过将此代码添加到你的 devblog_register_plugin_templates() 函数中来注册 Book: Canvas 模板:

register_block_template( 'devblog-plugin-templates//book-canvas', [
	'title'       => __( 'Book: Canvas', 'devblog-plugin-templates' ),
	'description' => __( 'An open template for use with single posts. Includes the Header, Post Content, and Footer.', 'devblog-plugin-templates' ),
	'post_types'  => [ 'book' ],
	'content'     => devblog_get_template_content( 'book-canvas.php' )
] );

与其他模板一样,它将在 外观 > 编辑器 > 模板 屏幕上为你的插件显示。但它也会出现在一个全新的位置。

首先,转到你的 Books 管理屏幕并选择一本书进行编辑。在侧边栏的 Book 面板下,找到 Template 选项并点击它。从弹出窗口中,选择 Swap template

WordPress 文章编辑屏幕。在侧边栏中,已选择 Template 选项,并且 Swap Template 选项已高亮显示。

现在,你应该会看到一个模态覆盖层,其中有一个选项可以切换到你的 Book: Canvas 模板。如果你选择它,它将在前端用于这本书:

WordPress 文章编辑屏幕上用于选择模板的弹出模态窗口。有一个可用的模板选项。

注册归档模板</h3