在 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 在这种情况下显示 空模板 文本,因为你尚未为其定义任何内容。
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 主题复制的。
一般来说,为你的插件模板复制最新默认主题的任何包装标记是一个好习惯,这将使其与许多其他主题最兼容。这是因为许多主题作者以默认主题为起点。
因为它是区块标记,所以技术上你可以使用任何内容,并且它可以在任何区块主题中正常工作而不会出错。但它可能无法完美适应每个主题的设计。
如果你刷新 模板 屏幕,你应该会在模板预览中看到你的更改:

当然,这个模板可以像任何其他模板一样由用户完全自定义。
专业技巧:更简洁的模板区块标记
我不喜欢将区块标记(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 中你的主题模板列表下显示如下:

一旦模板存在于主题中,它将位于 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 项。现在添加一些快速演示文章进行测试:

在使用自定义文章类型时,理解并运用模板层次结构很重要。通过使用标准的模板 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 模板列在插件面板下:

像任何其他模板一样,这也可以被主题覆盖或由用户自定义。
创建自定义模板
除了文章类型的普通单篇文章模板外,你还可以创建一个或多个用户可以为单篇文章选择的自定义模板。让我们为 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:

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