搜索全站
主题 19 分钟阅读

WordPress 注册区块模式:register_block_pattern 与 patterns 目录

每次搭落地页都要重新摆一遍「标题+三栏+按钮」?把常用布局注册成区块模式,编辑点一下就插好。本文讲 PHP 注册、patterns 目录自动扫描、分类管理与远程模式的关闭方法。

U
UFO_PF 2022-07-13 · 阅读 19 分钟
Wo 主题
阅读提示
本文约 7,594 字,预计阅读 19 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:编辑在重复搭同样的积木

客户站点有三十个落地页,每页都是「大标题 + 副标题 + 两个按钮 + 三栏特性卡 + FAQ」。编辑每次都要从空白页开始:插入封面区块、调对齐、插入列区块、切成三列、每列里再插标题段落……半小时过去了,做出来的间距还和上一页差两个像素。

区块模式(Block Patterns)就是把这套「积木组合」预先拼好存起来,编辑在插入器里点一下,整段结构连同内容一起进来,之后再改文字即可。它和「可复用区块」的区别是:模式是模板,插入后与原模式脱离关系,改一篇不影响其他;可复用区块是实例,改一处全站同步。需要全站统一更新的选可复用区块,需要「结构一致、内容各异」的选模式。

原理分析:三种来源与加载顺序

WordPress 的区块模式有三个来源:

来源 位置 说明
核心捆绑 core 分类 WP 自带的几十个模式,英文为主
远程模式 pattern directory(patterns.api.w.org) 从 WordPress.org 拉取,国内服务器常因网络慢拖累编辑器
主题/插件注册 patterns/*.php 或 register_block_pattern() 自己写的,可控性最高

主题目录下放 patterns/ 文件夹时,WordPress 会自动扫描里面的 PHP 文件,读取文件头的注释字段来注册,不需要写一行 PHP 代码——这是区块主题(FSE)的标准做法,内部由 register_theme_block_patterns() 完成。经典主题也可以用,只要主题声明了区块支持。

文件头支持的字段有:Title(必填)、Slug(必填,格式 theme-slug/pattern-name)、Categories、Description、Keywords、Viewport Width、Block Types(把模式绑定到某个区块的「初始内容」)、Post Types、Inserter(yes/no,是否在插入器里显示)。

国内站点强烈建议关闭远程模式:编辑器每次打开都要请求 patterns.api.w.org,超时会让插入器转圈好几秒。

保姆级实操

第一步:用目录方式注册,零 PHP 代码

在主题根目录建 patterns/hero-cover.php:

<?php
/**
 * Title: 首页主视觉
 * Slug: mimangfei/hero-cover
 * Categories: featured, header
 * Description: 带大标题、副标题与双按钮的全宽主视觉区
 * Keywords: hero, banner, 首屏
 * Viewport Width: 1200
 */
?>
<!-- wp:cover {"url":"<?php echo esc_url( get_template_directory_uri() ); ?>/assets/img/hero.jpg","dimRatio":50,"overlayColor":"contrast","align":"full","style":{"spacing":{"padding":{"top":"var(--wp--preset--spacing--60)","bottom":"var(--wp--preset--spacing--60)"}}}} -->
<div class="wp-block-cover alignfull"><span aria-hidden="true" class="wp-block-cover__background has-contrast-background-color has-background-dim"></span><div class="wp-block-cover__inner-container">
<!-- wp:heading {"textAlign":"center","level":1,"style":{"typography":{"fontSize":"3rem"}}} -->
<h1 class="wp-block-heading has-text-align-center" style="font-size:3rem">为外贸独立站打造的 WordPress 主题</h1>
<!-- /wp:heading -->

<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">轻量、合规、可维护,交付后客户自己就能改。</p>
<!-- /wp:paragraph -->

<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
<div class="wp-block-buttons">
<!-- wp:button {"backgroundColor":"accent"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-accent-background-color has-background wp-block-button__link--href">查看演示</a></div>
<!-- /wp:button -->

<!-- wp:button {"className":"is-style-ghost"} -->
<div class="wp-block-button is-style-ghost"><a class="wp-block-button__link wp-block-button__link--href">联系我们</a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div></div>
<!-- /wp:cover -->

重点是注释头那段,正文里的区块标记(block markup)可以从编辑器里「复制为代码块」拿到:在编辑器中选中区块,点右上角菜单选「复制」,粘贴到文本编辑器里就是这段注释标记。手写很容易因为属性转义出错,复制是最可靠的做法。

第二步:用 PHP 动态注册(内容需要计算时)

add_action( 'init', 'mimangfei_register_patterns' );

function mimangfei_register_patterns() {

    register_block_pattern_category(
        'mimangfei-pages',
        array(
            'label' => __( '页面模板', 'mimangfei' ),
        )
    );

    register_block_pattern(
        'mimangfei/cta-box',
        array(
            'title'         => __( '行动号召卡片', 'mimangfei' ),
            'description'   => __( '带标题、说明与按钮的居中标语区', 'mimangfei' ),
            'categories'    => array( 'mimangfei-pages', 'call-to-action' ),
            'keywords'      => array( 'cta', '按钮', '转化' ),
            'viewportWidth' => 900,
            'content'       => '<!-- wp:group {"style":{"spacing":{"padding":{"top":"var(--wp--preset--spacing--50)","bottom":"var(--wp--preset--spacing--50)"}}},"backgroundColor":"base-2","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-base-2-background-color has-background">
<!-- wp:heading {"textAlign":"center"} --><h2 class="wp-block-heading has-text-align-center">准备好开始了吗</h2><!-- /wp:heading -->
<!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center">留下需求,我们会在一个工作日内回复方案。</p><!-- /wp:paragraph -->
<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} --><div class="wp-block-buttons"><!-- wp:button --><div class="wp-block-button"><a class="wp-block-button__link wp-block-button__link--href">联系顾问</a></div><!-- /wp:button --></div><!-- /wp:buttons -->
</div>
<!-- /wp:group -->',
        )
    );
}

注意 register_block_pattern_category 要先于 register_block_pattern 调用,否则分类会出现但未归类。也可以在 content 里拼接变量(比如主题目录 URI),这是目录方式做不到的。

第三步:关闭远程模式与核心模式

add_filter( 'should_load_remote_block_patterns', '__return_false' );

add_action( 'after_setup_theme', 'mimangfei_disable_core_patterns' );

function mimangfei_disable_core_patterns() {
    remove_theme_support( 'core-block-patterns' );
}

should_load_remote_block_patterns 只关远程拉取,remove_theme_support( 'core-block-patterns' ) 会连核心捆绑的模式一起关掉。建议只关远程,保留核心——但核心模式多为英文内容,中文站也可以全关,只留自己注册的。

第四步:把模式绑定到区块(Block Types)

在 patterns/ 文件头加一行,可以让新建某个区块时自动套用这个模式:

<?php
/**
 * Title: 定价表起始内容
 * Slug: mimangfei/pricing-starter
 * Categories: mimangfei-pages
 * Block Types: core/table
 * Inserter: no
 */
?>

Inserter: no 表示不在插入器里显示,只作为区块的初始内容——非常适合「表格、图库」这类用户不知从何下手的区块。

第五步:按文章类型限制模式

register_block_pattern(
    'mimangfei/product-intro',
    array(
        'title'       => __( '产品介绍结构', 'mimangfei' ),
        'categories'  => array( 'mimangfei-pages' ),
        'postTypes'   => array( 'product', 'page' ),
        'content'     => '<!-- wp:paragraph --><p>产品亮点说明</p><!-- /wp:paragraph -->',
    )
);

postTypes 限定它只在指定文章类型出现,避免编辑在写普通文章时被一堆无关模式干扰。

第六步:卸载不需要的模式

add_action( 'init', 'mimangfei_unregister_patterns', 20 );

function mimangfei_unregister_patterns() {
    unregister_block_pattern( 'core/two-buttons' );
    unregister_block_pattern_category( 'query' );
}

优先级给到 20,确保晚于核心的注册时机。

常见踩坑

  1. Slug 少了主题前缀:hero 这种短名会与核心或其他插件冲突,必须写成 mimangfei/hero。
  2. 注释头缩进或格式错误:Slug: 前有空格、字段拼写错(如 Category 少 s),都会导致文件被跳过且不报错。
  3. block markup 属性里的引号未转义:PHP 文件里用双引号包裹 JSON 属性时,内部引号要用 &quot; 或改写为单引号拼接,否则模式插入后区块报错「此块包含意外或无效的内容」。
  4. 关掉远程后又抱怨没素材:关闭前先把官方模式里能用的手动复制进自己的 patterns 目录。
  5. 模式里的图片路径写死:主题换域名或换目录名后图片全裂,用 get_template_directory_uri() 动态拼接,或改用媒体库 URL。
  6. 案例:某站 patterns/ 目录下放了 40 个模式文件,其中一个忘了写 Slug,WordPress 扫描时静默跳过;更糟的是另一个文件写了 // 注释 单行注释,导致整个文件的 mark-up 被当成纯文本输出,插入后页面上出现一整段 <!-- wp:heading --> 源码。后来加了 CI 步骤,用正则校验每个文件头都必须同时包含 Title 与 Slug 才允许提交。
  7. Viewport Width 不写:插入器缩略图会被拉伸变形,编辑难以分辨,建议统一填 1200 或实际宽度。
  8. 模式引用了主题自定义区块样式但未注册:插入后看到的是无样式裸结构,确认 区块样式变体 里注册的变体类名与模式中的 className 一致。

总结

落地顺序:先把站点重复度最高的三个布局抽成模式(首屏、特性三栏、FAQ),放进 patterns/ 目录;需要动态内容或条件判断的部分改用 register_block_pattern();上线前关闭远程模式并把 Inserter: no 用在该用的地方。模式的价值不在于多,而在于「编辑最常用的那几次点击」被省掉,所以宁可精挑 5 个也别堆 50 个。想要进一步减少重复劳动,可配合 区块样式变体 统一外观,或按 主题打包与发布规范 把模式一起交付给客户。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。