gebruederheitz/wp-block-updater

使用 innerBlocks 更新动态块

2.0.2 2023-09-28 08:11 UTC

README

使用 innerBlocks 更新动态块

从使用 React 渲染的 "静态" Gutenberg 块(块编辑器的 save() 方法返回块的标记,该标记只渲染一次并作为静态 HTML 写入到文章内容中)迁移到 "动态" 块(由 PHP 渲染)是微不足道的。我们不是让 save() 返回标记,而是让它返回 null,让 PHP 模板处理块的前端输出。但有一个例外:当受影响的块包含 "innerBlocks" 时,它们的渲染通常仍然需要由 Gutenberg & React 处理,所以我们简单地从 save() 返回 <InnerBlocks.Content /> – 这将导致无效的块,因为所有现有的块仍然包含完整的标记,而不仅仅是 innerBlocks。此包提供了一种 REST 接口来跨文章更新此类块,并允许通过管理页面运行针对所有已发布文章的批量更新。

警告

这不是一个通用的块更新器;它只能正确处理上述任务:将具有 innerBlocks 的静态渲染块迁移到动态块。

在此工具上运行静态块将使该块的标记从您的 WordPress 前端中消失(部分或全部)!

对此工具针对没有 innerBlocks 的动态块运行将没有任何影响。

安装

通过 composer

> composer require gebruederheitz/wp-theme-docs

确保您有 Composer 自动加载或替代类加载器。

用法

实例化 BlockUpdater,例如在您的 functions.php 中,传递一个合格块数组(即从静态渲染转移到动态渲染的块)

new \Gebruederheitz\Wordpress\BlockUpdater\BlockUpdater(
    ['mynamespace/myblock']
);

现在转到 wordpress/wp-admin/tools.php?page=ghwp-block-updater,选择一个块,然后单击 "开始" 以遍历类型为 pagepost 的所有已发布文章,并在所选块存在的情况下重新渲染其块内容。

示例场景

之前

registerBlockType('my/block', {
    title: 'My Block',
    icon: 'someicon',
    description: '...',
    category: 'layout',
    styles: [/*...*/],
    attributes: {/*...*/},
    edit(props) {
        /* ... */
        return <MyEditComponent {...props} />;
    },
    /* A React-rendered (static) block with innerBlocks */
    save(props) {
        return (
            <div className="my-component">
                <h1>{props.attributes.title}</h1>
                <InnerBlocks.Content />
            </div>
        );
    },
});

现在

registerBlockType('my/block', {
    title: 'My Block',
    icon: 'someicon',
    description: '...',
    category: 'layout',
    styles: [/*...*/],
    attributes: {/*...*/},
    edit(props) {
        /* ... */
        return <MyEditComponent {...props} />;
    },
    /* Only innerBlocks are returned, the rest left to PHP */
    save() {
        return <InnerBlocks.Content />;
    },
});
register_block_type('my/block', [
    'editor_script' => 'myblock.js',
    'render_callback' => function(array $attributes = [], string $content = '') {
        foreach ($attributes as $name => $datum) {
            set_query_var($name, $datum);
        }
        if (!empty($content)) {
            set_query_var('innerBlocks', $content);
        }
        if (!empty($attributes['className'])) {
            set_query_var('className', $attributes['className']);
        }
        
        ob_start();
        load_template('template-parts/blocks/my-block.php', false, $data);
        return ob_get_clean();
    },
    'attributes' => [
        'title' => [
            'type' => 'string',
            'default' => 'Hello World',
        ],       
    ],
]);
# template-parts/blocks/my-block.php
<?php
    $innerBlocks = get_query_var('innerBlocks');
    $title = get_query_var('title');
?>
<div class="my-block">
    <h1><?= $title ?></h1>
    <?= $innerBlocks ?>
</div>

对于任何尚未迁移的页面,这会导致块在其内部重复,因为 $content 仍然包含更改之前渲染的整个块。

之后

$content 将被重新解析和重新渲染,因此它只包含实际的 innerBlocks,使块在前后端都正常工作。

开发

依赖

  • PHP >= 7.4
  • Composer 2.x
  • nodeJS LTS (v18.x); 建议使用 asdf
  • 可选:GNU Make (或替代方案)