🆕 Bricks 2.4 已发布:查询循环性能提升 40%,迁移教程同步更新 →

首页 / 中文教程 / 教程

Bricks 自定义元素开发入门:扩展 Element 类,写一个自己的元素

教程:Bricks 自定义元素开发入门——扩展 Bricks Element 类创建自己的元素,含控件定义、前端渲染、注册加载与代码签名机制,适合外贸独立站与 WordPress 开发者。

Ray ChanRay Chan·2026-08-18·约 7 分钟
目录
  1. 1.自定义元素是什么
  2. 2.准备工作:子主题与文件结构
  3. 3.空白元素类骨架
  4. 4.元素属性与方法速查表
  5. 5.填充一个完整示例元素
  6. 6.控件组与控件
  7. 7.前端渲染与动态数据
  8. 8.加载与注册你的元素
  9. 9.代码签名:保护可执行代码
  10. 10.常见问题(FAQ)

Bricks 的能力不止于点选拖拽——你完全可以在子主题里写 PHP 类,扩展 Bricks 的 Element 基类,创建真正属于自己的元素。这类自定义元素会像原生元素一样出现在构建器面板里,拥有自己的分类、图标、控件(settings)、样式入口和前端渲染逻辑,甚至能做成可嵌套元素(nestable)。

本文依据 Bricks 官方文档《Create Your Own Elements》与《Code signatures》改写,覆盖从零写一个元素的全过程,以及配套的代码签名机制——它决定了你写的可执行 PHP/HTML 代码能否安全运行。

自定义元素是什么

在 Bricks 中创建自定义元素,模式与创建 WordPress widget 非常相似:继承 \Bricks\Element 基类,按需填充属性和方法即可。

官方子主题(可从你的 Bricks 账户 下载)里自带一个演示用的自定义元素,本文以它为基础展开讲解。一个典型的开发流程是:

步骤 做什么 产物
1 在子主题根目录新建元素类文件 element-test.php
2 写类:定义属性、控件、渲染逻辑 Prefix_Element_Test
3 functions.php 里注册元素 Bricks\Elements::register_element()
4 打开构建器,像用原生元素一样使用 面板中出现自定义元素

整个过程不需要动 Bricks 核心文件,也不影响后续升级。

准备工作:子主题与文件结构

自定义元素代码必须放在子主题里(不要改父主题,否则 Bricks 升级会被覆盖)。如果你还没有子主题,先从 my.bricksbuilder.io 下载官方子主题并启用。

先在子主题根目录新建一个文件 element-test.php,后面所有元素代码都写在这个文件里。

空白元素类骨架

一个空白的元素类长这样——先看结构,再逐个理解:

<?php

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class Prefix_Element_Test extends \Bricks\Element {

  // Element properties

  public $category     = '';

  public $name         = '';

  public $icon         = '';

  public $css_selector = '';

  public $scripts      = [];

  public $nestable     = false; // true || @since 1.5

  // Methods: Builder-specific

  public function get_label() {}

  public function get_keywords() {}

  public function set_control_groups() {}

  public function set_controls() {}

  // Methods: Frontend-specific

  public function enqueue_scripts() {}

  public function render() {}

}

可以看到类由两部分组成:属性(properties,描述元素的元信息)和方法(methods,构建器侧与前端侧的行为)。下面把每一项讲清楚。

元素属性与方法速查表

成员 必填 作用与规则
$category 元素在构建器面板中的分类名(全小写、无空格)。可以用预置分类(如 generalmedia),也可以自定义新分类;自定义分类需要用 bricks/builder/i18n 过滤器提供可翻译的分类名
$name 元素的唯一标识(全小写、无空格)。为避免与其他元素冲突,务必加前缀,如 prefix-element-test
$icon 图标字体 CSS 类,决定元素在面板里显示什么图标。Bricks 内置 Fontawesome 6(如 fas fa-anchor)、Ionicons 4(如 ion-md-alarm)、Themify Icons(如 ti-bolt-alt
$css_selector 默认所有 CSS 控件设置都作用在元素外层 .bricks-element-wrapper 上;想让默认 CSS 选择器指向某个子元素,就在这里指定
$nestable 普通元素省略即可;设为 true 可创建可嵌套元素(nestable element)
$scripts 元素在前端渲染或构建器中更新时要运行的 JS 脚本名数组。例如 Counter 元素用 bricksCounter(定义在 frontend.min.js 里),加载方式:public $scripts = ['bricksCounter'];所有脚本名都要加前缀,如 prefixElementTest
get_label() 返回本地化(可翻译)的元素标签
get_keywords() 字符串数组,构建器搜索元素时匹配这些关键词就能搜到该元素
set_control_groups() 默认所有控件都无分组地堆在「Content」标签下;想给控件分组就在这里定义控件组:title(本地化组名)+ tabcontentstyle
set_controls() 定义元素的控件(设置项)。所有可用控件类型见官方 Element Controls 文档
enqueue_scripts() 加载元素专属的脚本与样式,只在用到该元素的页面上加载,性能更好。示例:wp_enqueue_script( 'prefix-element-test', get_template_directory_uri() . '/js/custom.js', ['jquery'], '1.0', true );
render() 渲染元素 HTML。用 $this->set_attribute() 设置 HTML 属性,用 $this->render_attributes() 输出
set_attribute( $key, $attribute, $value ) 为任意 HTML 标签设置属性的辅助方法:$key 是该标签的唯一标识,$attribute 是属性名,$value 是字符串或数组
render_attributes( $key ) 输出通过 set_attribute() 设置的属性,$key 是同一个标识
render_dynamic_data_tag( $tag, $context, $args ) 在 render 里渲染动态数据标签的辅助方法(如 {post_title}),会自动根据渲染环境设置正确的 post ID
render_dynamic_data( $content ) 在 render 里渲染可能包含动态数据标签的内容字符串,同样会自动处理 post ID

填充一个完整示例元素

把上面的骨架填上真实数据,就是一个可用的「提示框」元素(带文本内容 + 类型下拉):

<?php

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class Prefix_Element_Test extends \Bricks\Element {

  // Element properties

  public $category     = 'general'; // Use predefined element category 'general'

  public $name         = 'prefix-test'; // Make sure to prefix your elements

  public $icon         = 'ti-bolt-alt'; // Themify icon font class

  public $css_selector = '.prefix-test-wrapper'; // Default CSS selector

  public $scripts      = ['prefixElementTest']; // Script(s) run when element is rendered on frontend or updated in builder

  // Return localised element label

  public function get_label() {

    return esc_html__( 'Test element', 'bricks' );

  }

  // Set builder control groups

  public function set_control_groups() {

    $this->control_groups['text'] = [ // Unique group identifier (lowercase, no spaces)

      'title' => esc_html__( 'Text', 'bricks' ), // Localized control group title

      'tab' => 'content', // Set to either "content" or "style"

    ];

    $this->control_groups['settings'] = [

      'title' => esc_html__( 'Settings', 'bricks' ),

      'tab' => 'content',

    ];

  }

  // Set builder controls

  public function set_controls() {

    $this->controls['content'] = [ // Unique control identifier (lowercase, no spaces)

      'tab' => 'content', // Control tab: content/style

      'group' => 'text', // Show under control group

      'label' => esc_html__( 'Content', 'bricks' ), // Control label

      'type' => 'text', // Control type

      'default' => esc_html__( 'Content goes here ..', 'bricks' ), // Default setting

    ];

    $this->controls['type'] = [

      'tab' => 'content',

      'group' => 'settings',

      'label' => esc_html__( 'Type', 'bricks' ),

      'type' => 'select',

      'options' => [

        'info' => esc_html__( 'Info', 'bricks' ),

        'success' => esc_html__( 'Success', 'bricks' ),

        'warning' => esc_html__( 'Warning', 'bricks' ),

        'danger' => esc_html__( 'Danger', 'bricks' ),

        'muted' => esc_html__( 'Muted', 'bricks' ),

      ],

      'inline' => true,

      'clearable' => false,

      'pasteStyles' => false,

      'default' => 'info',

    ];

  }

  // Enqueue element styles and scripts

  public function enqueue_scripts() {

    wp_enqueue_script( 'prefix-test-script' );

  }

  // Render element HTML

  public function render() {

    // Set element attributes

    $root_classes[] = 'prefix-test-wrapper';

    if ( ! empty( $this->settings['type'] ) ) {

      $root_classes[] = "color-{$this->settings['type']}";

    }

    // Add 'class' attribute to element root tag

    $this->set_attribute( '_root', 'class', $root_classes );

    // Render element HTML

    // '_root' attribute is required (contains element ID, class, etc.)

    echo "<div {$this->render_attributes( '_root' )}>"; // Element root attributes

      if ( ! empty( $this->settings['content'] ) ) {

        echo "<div>{$this->settings['content']}</div>";

      }

    echo '</div>';

  }

}

几个要点:

  • 所有元素的设置值都存在 $this->settings。想在 render() 里看当前元素有哪些设置,直接 var_dump( $this->settings ); 打印即可;
  • 控件标识(如 contenttype)全小写无空格,与控件组标识、元素 name 规则一致;
  • $this->settings['content'] 就是用户在构建器里输入的内容,$this->settings['type'] 是下拉框选中的值,render 时用来拼 color-xxx 的 class。

控件组与控件

set_control_groups() 负责把控件归组。示例里定义了两个组:

  • text 组(标题 Text,tab => 'content')——承载文本内容控件;
  • settings 组(标题 Settings,tab => 'content')——承载类型选择控件。

set_controls() 里每个控件数组的常用键如下(示例中用到的):tab(归属标签页 content/style)、group(归属哪个控件组)、label(控件显示名)、type(控件类型)、default(默认值),下拉类控件还有 optionsinlineclearablepasteStyles

Bricks 的控件类型远不止 textselect——完整的控件清单、每个控件的全部参数,请查阅官方文档 Element Controls,页面里对每种控件都有参数表,直接照抄参数就能用。

前端渲染与动态数据

render() 是元素真正输出 HTML 的地方,规则很简单:

  • $this->set_attribute( '_root', 'class', $root_classes ) 给根标签设置属性——_root 是必需的,它承载元素的 ID、class 等关键属性;
  • $this->render_attributes( '_root' ) 输出这些属性;
  • 直接 echo 输出 HTML 字符串。

如果元素里要渲染动态数据标签(比如 {post_title}),不要手动拼字符串,用官方提供的两个辅助方法:

  • $this->render_dynamic_data_tag( $tag, $context, $args ) —— 渲染单个动态数据标签;
  • $this->render_dynamic_data( $content ) —— 渲染可能包含多个动态数据标签的内容字符串。

这两个方法会自动根据元素实际渲染的环境(文章页、归档页、循环内等)设置正确的 post ID,避免出现「在循环里取错文章标题」的经典问题。

加载与注册你的元素

写完类之后,还需要让 Bricks 知道它的存在。打开子主题的 functions.php,粘贴以下代码:

/**
 * Register custom elements
 */
add_action( 'init', function() {

  $element_files = [
    __DIR__ . '/element-test.php',
  ];

  foreach ( $element_files as $file ) {
    \Bricks\Elements::register_element( $file );
  }

}, 11 );

register_element 方法接受 3 个参数:

参数 必填 说明
$file 自定义元素 PHP 文件在服务器上的完整路径
$name 自定义元素的 name 字符串(如 prefix-element-test
$element_class 元素类名(如 Prefix_Element_Test),必须派生自 \Bricks\Element

性能提示:带上 $name$element_class 两个可选参数能提升加载性能。多元素站点建议在 $element_files 数组里列出所有元素文件,一次注册完。

注册完成后,刷新构建器,就能在「General」分类(或你自定义的分类)里找到这个 Test element,拖进画布、设置内容、选择类型,前端会渲染出对应的 HTML。

代码签名:保护可执行代码

如果你的自定义元素涉及可执行代码(Code 元素的 PHP/HTML、SVG 代码、查询循环编辑器代码等),Bricks 还要求它们持有有效的代码签名才能运行。签名机制与元素开发直接相关——元素里的 PHP 代码再强大,签名缺失或失效时 Bricks 一律不执行。

原理:签名时 Bricks 用 WordPress 的 wp_hash() 对代码做哈希,并把签名和 Bricks 数据一起存储;运行时再次哈希比对,不一致就阻止执行。这样即使攻击者拿到数据库写入权限、塞进恶意代码,只要生成不了有效签名,代码就不会运行。

需要签名的代码位置

  • Code 元素启用了 Execute code 时的 PHP/HTML 代码;
  • SVG 元素 Source 设为 Code 时;
  • 查询循环(Query Loop)编辑器代码;
  • 组件(Component)查询属性;
  • 全局查询记录。

签名的前置条件

  • 必须在 Bricks → Settings → Custom code 中启用代码执行(Code execution);
  • 用户必须拥有 Bricks 的 Execute code 能力(capability);
  • 构建器内手动生成签名是管理员级别操作;全局重新生成签名需要 WordPress 的 manage_options 权限;
  • 如果常量 BRICKS_LOCK_CODE_SIGNATUREStrue,无论什么权限都无法生成新签名。

如何生成签名

场景 操作
单个元素 构建器中打开代码编辑器,点代码框上方的 Sign code 按钮;光标在编辑器内时也可按 CMD/CTRL + R。签名后保存页面,代码与签名会一起存储
整页批量 构建器结构面板顶部的红色指纹图标会提示存在未签名代码,点它可查看并批量签名当前页所有未签名元素
全站 后台 Bricks → Settings → Custom code → Code signatures,点 Regenerate code signatures,会为所有页面、模板、全局元素、组件元素树、组件查询属性、全局查询记录生成签名

锁定签名生成(官方文档标注该常量自 Bricks 1.11.1 引入):高安全环境可以在签名前定义常量,此后任何生成签名的尝试都会返回「Code signatures are locked」错误:

if ( ! defined( 'BRICKS_LOCK_CODE_SIGNATURES' ) ) {

    define( 'BRICKS_LOCK_CODE_SIGNATURES', true );

}

什么时候必须重新生成签名

  • 从 1.9.7 之前的版本升级 Bricks——官方文档明确:升级后必须到 Bricks → Settings → Custom code 生成签名,已签名的代码位置才会运行,建议先做一次代码审查;
  • 修改过 WordPress saltswp-config.php 里的密钥)——salts 一变,已有签名全部失效;
  • 站点迁移(换域名或换服务器)——新环境 salts 不同就需要重新签名;
  • 编辑过已签名代码——内容变了签名就不匹配,需要重新签名后才能运行。

salts 是 WordPress 的哈希密钥,Bricks 的签名依赖它们,所以「同一份代码换环境签名就失效」是正常现象,重新签名即可。

常见问题(FAQ)

Q:自定义元素会出现在构建器哪个分类里? A:由 $category 属性决定。填官方预置分类(如 general)就进对应分类;填自定义名称会创建新分类,记得用 bricks/builder/i18n 过滤器提供可翻译的分类名。

Q:元素注册了但构建器里看不到? A:先确认 functions.php 里的注册代码生效(add_action( 'init', ... )),再确认元素类名正确派生自 \Bricks\Element 且文件路径正确。注册后需要刷新构建器页面。

Q:控件不显示是什么原因? A:set_controls() 是必填方法,控件数组的键、labeltype 必须完整;控件组没定义时控件会无分组显示在 Content 标签下,这是正常的。

Q:为什么升级 Bricks 或改密钥后,Code 元素不执行了? A:代码签名失效了。按上面的「什么时候必须重新生成签名」检查——改过 salts、迁移过站点、升级自 1.9.7 之前,都需要重新生成签名。

Q:自定义元素怎么加载自己的 CSS/JS? A:用 enqueue_scripts() 方法,按需加载、只在用到该元素的页面加载;构建器内要跑的脚本则放进 $scripts 数组。

延伸阅读

Ray Chan

站长

Ray Chan

WordPress Developer & Bricks Specialist

WordPress developer with 10+ years of client builds. Switched to Bricks in 2023 — now builds fast WordPress sites and migrates legacy Elementor/Divi projects.

延伸阅读