创建自定义古腾堡块——第 9 部分:动态块和 PHP 渲染
到目前为止,我们已经用 Javascript 渲染了块的输出。然而,对于像最近的帖子或显示帖子这样的动态内容,我们需要在 PHP 中呈现块的输出。在这篇文章中,我们将了解如何以及为什么。
本文涉及的内容包括:
为什么我们需要以不同的方式处理动态块?
有些例子是显而易见的;显示类别中最新帖子的块是动态的,因为帖子会随时间变化。您不选择块中的帖子;相反,您可能会有选择类别的设置、为每个帖子显示的信息、帖子的数量、列的数量等等。每次 WordPress 使用此块加载帖子时,它需要在那时查询 WordPress 以获取最新帖子。一个月后查看同一篇帖子可能会产生不同的结果,即使带有该块的帖子本身尚未更新。
但动态块的必要性有时并不那么明显。您可能会想象一个特色帖子块,您可以在其中选择一个特定的帖子来显示它,不一定是动态的。但它可以——而且应该是。请记住,所选帖子可以随时更新其标题、摘录或特色图片——这应该反映在该帖子的特色版块中。
为了制作一个用于显示单个帖子的非动态块,您需要在块的属性中保存帖子 ID、其 URL、特色图像 URL、摘录字符串或预览帖子所需的任何内容。这就是问题所在。如果您更新所选帖子的特色图片,具有特色帖子块的帖子将不会自动更新其属性。它将与旧特色图片的 URL 一起保存。只有当你用区块编辑帖子,并确保它用更新的信息重新保存属性时,区块才会显示正确的更新信息。
因此,无论何时我们处理动态内容——帖子、类别或任何可能随时间变化的内容——我们都在处理动态块。对于动态块,我们需要使用 PHP(服务器端代码)来呈现我们的块,以确保它在每次呈现时都能检索更新的信息。
编辑器中动态块的性质发生了变化
当您开始开发动态块时,编辑器中块的性质将会改变。您的块的edit
功能通常也需要是动态的。例如,对于特色帖子块,您需要获取帖子以供选择,或者对于最新消息块,您需要检索类别列表以供用户选择。
完全可以通过执行 AJAX 请求从编辑器中从 WordPress 请求信息——使用包和组件或使用WordPress REST API手动执行它们。无论您采用哪种方法,您的块都需要处理异步输入流——等待响应的时间范围。
有多种方法和模式可以为古腾堡创建动态块。最常见的是,您将使用一种称为高阶组件的 React 模式,WordPress 为其提供了大量功能和组件。
在下一个教程部分,我们将了解如何获取帖子以及如何检索我们块中的类别。现在我们需要学习如何让 PHP 渲染我们的块。
让我们的块为 PHP 渲染做好准备
我们需要在 Javascript 中做的主要部分是使块的save
函数返回null
。您可以保留原始输出,但是一旦我们告诉 WordPress 使用 PHP 来呈现块,这将被忽略。为了让我们自己和其他人清楚地知道块的输出不是用 Javascript 处理的,我们将更改save
函数。
registerBlockType(‘awp/firstblock’, {
title: __(‘My first block’, ‘awhitepixel’),
category: ‘common’,
…
edit: FirstBlockEdit,
save: () => { return null }
});
不要忘记更改保存功能会使所有现有块都损坏。重新添加块。该块应该像以前一样工作;使用设置和更新属性。它现在不会在前端输出任何内容。评论块将在那里,将所有属性存储在 JSON 中,但不会呈现可见的 HTML。
然而; 如果您的任何属性正在使用该source
属性,则需要更改它。使用 PHP 呈现的块不支持这一点,因为它们是直接从保存的输出中解析的——我们现在返回null
。我们在我们的块中的第二个上使用源RichText
– 用于段落。此时编辑器根本不会保存你放入其中的内容RichText
。
因此,如果您还在属性上使用source
,myRichText
我们需要删除source
和selector
属性以确保属性将被存储而不是从save
函数中解析:
attributes: {
…
myRichText: {
type: ‘string’,
},
…
在此之后,我们的块已准备好在 PHP 中呈现。我们可以留下 Javascript 文件(不要忘记构建它),其余的在 PHP 中完成。
在 PHP 中渲染块
为了告诉 WordPress 在 PHP 中呈现块的输出,我们向函数添加了一个新参数register_block_type()
。我们需要将键render_callback
和它应该运行的函数的值一起添加到数组中。
functions.php中
add_action(‘init’, function() {
register_block_type(‘awp/firstblock’, [
‘editor_script’ => ‘awp-myfirstblock-js’,
‘render_callback’ => ‘awp_myfirstblock_render’
]);
});
PHP渲染函数
awp_myfirstblock_render
让我们进一步定义该函数functions.php
(或您放置 PHP 代码的任何位置)。我们的函数将获得两个参数;我们称他们为$attr
and $content
。
functions.php中
function awp_myfirstblock_render($attr, $content) {
// return the block’s output here
}
该参数$attr
将是一个包含所有已保存属性的关联数组。第二个参数,$content
用于我们块内的块。这仅与支持嵌套块的块有关——例如 Columns 或 Cover。
该功能应该永远不会echo
出任何东西。必须返回所有输出,因此您需要构建一个字符串并在最后返回它。
关于属性需要记住的重要一点是,只有保存的属性才会出现在函数的第一个参数中。如果一个属性实际上从未被更改和保存——即仅仅依赖于它default
,那么我们的 PHP 函数根本不会包含该属性。
if (isset($attr['...']))
您需要通过始终检查或更可取的方式来处理此问题:在我们的register_block_type()
调用中定义属性。我们可以提供另一个键 ,attributes
并将其值设置为一个数组,其中包含我们希望从块中提取的所有属性。该结构应该与您在 Javascript 中定义的结构相同,但您需要在 PHP 数组中使用它而不是 Javascript 对象。重新定义相同的属性可能有点麻烦,但使用智能代码编辑器应该可以非常快速地将其复制+粘贴并多行编辑到 PHP 中。
为我们的渲染函数添加属性
让我们将新attributes
元素添加register_block_type()
并粘贴到我们在 Javascript 文件中定义的完全相同的属性中:
functions.php中
add_action(‘init’, function() {
register_block_type(‘awp/firstblock’, [
‘editor_script’ => ‘awp-myfirstblock-js’,
‘render_callback’ => ‘awp_myfirstblock_render’,
‘attributes’ => [
‘myRichHeading’ => [
‘type’ => ‘string’
],
‘myRichText’ => [
‘type’ => ‘string’
],
‘textAlignment’ => [
‘type’ => ‘string’,
],
‘toggle’ => [
‘type’ => ‘boolean’,
‘default’ => true
],
‘favoriteAnimal’ => [
‘type’ => ‘string’,
‘default’ => ‘dogs’
],
‘favoriteColor’ ==> [
‘type’ => ‘string’,
‘default’ => ‘#DDDDDD’
],
‘activateLasers’ => [
‘type’ => ‘boolean’,
‘default’ => false
],
]
]);
});function awp_myfirstblock_render($attr, $content) {
return ‘<div>’.$attr[‘favoriteColor’].'</div>’;
}
请记住,如果您default
为所有属性定义 a,则函数的$attr
参数应始终包含所有属性。例如,textAlignment
上面的属性只有在它被更改时才会存在$attr
——你需要检查 isset($attr['textAlignment'])
.
至于函数的 HTML 输出,这完全取决于您!
从内部编辑器请求 PHP 渲染
可以在编辑器中请求我们块的 PHP 渲染。如果您希望能够在编辑器中预览块的输出,这将很有用。ServerSideRender
我们可以使用从包中调用的组件来做到这一点wp.editor
。
作为道具,ServerSideRender
您需要定义您希望传递的所有属性。至少您需要向 prop 提供块的名称block
,以便 WordPress 知道要查找哪种渲染方法。这是供您使用props.name
的edit
功能。您还需要在 prop 中提供您需要的任何属性attributes
。如果需要,您也可以在此处的属性之外添加自定义变量。请记住,这只适用于内部编辑器,而不适用于前端。
您不能ServerSideRender
在块的save
功能中使用。您的save
函数仍必须返回null
。
让我们ServerSideRender
在我们的块中实施以在实践中看到它。
使用 ServerSideRender 进行块预览/编辑模式
如果您按照上一步为我们的块制作了预览/编辑模式切换器,我们现在可以ServerSideRender
在切换到预览模式时使用 PHP 渲染块的预览。
首先我们需要记住ServerSideRender
在顶部进行解构:
const { ServerSideRender } = wp.editor;
如果您还记得我们在上一步中使用了组件Disabled
和/或Placeholder
来进行预览。使用的问题Placeholder
是我们将不需要的样式应用于我们的输出。让我们替换Placeholder
为ServerSideRender
. 您可以选择保留该Disabled
组件,以确保其内容不可点击或可拖动。
在属性editMode
为 false 时渲染块的代码中,我们这样做:
…
{!this.state.editMode &&
<ServerSideRender
block={this.props.name}
attributes={{
myRichHeading: attributes.myRichHeading,
myRichText: attributes.myRichText,
textAlignment: attributes.textAlignment,
toggle: attributes.toggle,
favoriteAnimal: attributes.favoriteAnimal,
favoriteColor: attributes.favoriteColor,
activateLasers: attributes.activateLasers
}}
/>
}
…
现在,当我们切换到预览模式时,工具栏中的自定义按钮将呈现 PHP 的输出。在前端查看帖子时,输出应该相同。这是确保编辑器和前端输出相同的好习惯。
示例:显示选定帖子的动态块
PHP 渲染函数中的输出可以是任何内容,并且您可以完全访问所有 WordPress 函数。假设一个块,其中一个帖子 ID 将保存在一个属性中。在render_callback
PHP 函数中,您可以根据 ID 查询帖子并输出其信息。如何做到这一点应该是不言自明的,但这里有一个简单的例子。
让我们添加一个类型为 number 的属性selectedPostId
:
attributes: {
selectedPostId: {
type: ‘number’
}
}
在我们块的edit
功能内部的某个地方,我们添加了一个TextControl
组件。它可以在任何你想要的地方——在块内或在检查器中。
<TextControl
label={__(“Type in post ID”, ‘awhitepixel’)}
type=”number”
value={attributes.selectedPostId}
onChange={(newval) => setAttributes({ selectedPostId: parseInt(newval) })}
/>
PHP部分
那应该已经处理了 Javascript 部分。让我们转向 PHP。首先,我们需要将新属性添加selectedPostId
到attributes
数组中register_block_type()
:
register_block_type(‘awp/firstblock’, [
‘editor_script’ => ‘awp-myfirstblock-js’,
‘render_callback’ => ‘awp_myfirstblock_render’,
‘attributes’ => [
‘selectedPostId’ => [
‘type’ => ‘number’,
‘default’ => 0
],
…
]
]);
在render_callback
函数中,我们现在可以使用 访问帖子 ID $attr['selectedPostId']
。我们可以用它执行一个简单的操作get_post()
并输出帖子的数据;它的链接和标题:
function awp_myfirstblock_render($attr, $content) {
$str = ”;
if ($attr[‘selectedPostId’] > 0) {
$post = get_post($attr[‘selectedPostId’]);
if (!$post) {
return $str;
}
$str = ‘<div class=”awp-myfirstblock”>’;
$str .= ‘<a href=”‘ . get_the_permalink($post) . ‘”>’;
$str .= ‘<h3>’ . get_the_title($post) . ‘</h3>’;
$str .= ‘</a>’;
$str .= ‘</div>’;
}
return $str;
}
这是一个非常基本的示例,可以作为您编写更高级和自定义代码的跳板。
现在我们知道如何处理渲染动态块,下一步就是学习如何使编辑器部分也更直观。在下一步中,我们将重点关注如何从块编辑器中查询帖子并为用户提供更好的选择帖子的方法。