如何构建纯PHP的古腾堡区块

如何构建纯PHP的古腾堡区块

文章目录

  • 什么是纯PHP区块?它们为何如此重要?
  • 如何构建您的第一个纯PHP古腾堡区块
  • 使用属性构建区块设置UI
  • 纯PHP区块的实际应用示例
  • 使用纯PHP将旧版短代码转换为古腾堡区块
  • 纯PHP代码区块如何改变WordPress开发?

如何构建纯PHP的古腾堡区块

多年来,要精通 Gutenberg 区块开发,需要深入了解 React 和 Node.js 等技术,以及复杂的构建步骤和 JavaScript 工具。

然而,WordPress 开发正在不断发展,现在您可以完全使用 PHP 构建和管理 Gutenberg 区块。

这对于那些不想使用 React 和服务器端 JavaScript (JS) 开发的开发者来说尤其有利。它降低了学习难度,简化了开发体验,并通过消除不必要的前端脚本开销来提高性能。

在接下来的章节中,您将学习如何利用这些新特性来构建纯 PHP 的 Gutenberg 区块。在此过程中,您将学会创建更精简、更快速、更易于维护的 WordPress 网站。

警告:请注意,本文中仅包含 PHP 区块的部分目前处于实验阶段,可能会有所更改。请勿在生产环境中使用此功能!

什么是纯PHP区块?它们为何如此重要?

传统上,创建 Gutenberg 区块需要高级的服务器端 JavaScript 和 React 编码技能。这成为资深 WordPress 开发者采用区块编辑器的一大障碍,因为他们可能缺乏必要的 ReactNode.js 知识。

现在情况正在改变。从 Gutenberg 21.8 开始,您可以使用纯 PHP 注册 Gutenberg 区块。这避免了为不熟悉服务器端 JavaScript 的用户搭建 Node.js 环境的复杂性。

通过纯 PHP 区块注册,您可以使用同一套 PHP 代码在编辑器和前端注册和显示区块。这鼓励使用混合主题或传统 PHP 函数和短代码的网站采用区块编辑器进行开发。

如果您想了解更多信息,请查看以下专门讨论纯 PHP 区块的主要 GitHub PR。

如何构建您的第一个纯PHP古腾堡区块

当一个区块仅在服务器端注册(不包含 JS 文件)且新的 auto_register 支持标志设置为 true 时,编辑器会自动使用 ServerSideRender 组件在客户端注册该区块并显示区块预览。本质上,区块的内容现在直接由编辑器和前端的 PHP 代码生成。

注:本文中的示例仅适用于已在开发网站上安装 Gutenberg 22.3 或更高版本的网站。

例如,以下是一个简单的 PHP 示例,它使用纯 PHP 方法注册一个区块。

/**
* Render callback (frontend and editor)
*/
function my_php_only_block_render( $attributes ) {
return '<div>
<h3>🚀 PHP-only Block</h3>
<p>This block was created with only PHP!</p>
</div>';
}
/**
* Register the block on the 'init' hook.
*/
add_action( 'init', function() {
register_block_type( 'my-plugin/php-only-test-block', array(
'title'           => 'My PHP-only Block',
'icon'            => 'welcome-learn-more',
'category'        => 'text',
'render_callback' => 'my_php_only_block_render',
'supports'        => array(
// Automatically registers the block in the Editor JS (previously auto_ssr)
'auto_register' => true, 
),
) );
});

您可以将此代码复制粘贴到自定义插件的主文件中进行测试。激活插件后,您应该会在区块插入器中看到“My PHP-Only Block”。

一个简单的纯 PHP 区块

一个简单的纯 PHP 区块

register_block_type  函数用于在服务器上注册区块类型。它现在支持新的 auto_register 属性,指示 Gutenberg 传递来自 PHP 注册的元数据。

该函数接受两个参数:

  • 区块类型的名称,包括命名空间。在本例中,区块名称为 my-plugin/php-only-test-block
  • 区块类型的参数数组。在上面的代码中,我们设置了 titleiconcategoryrender_callback, 和 supports。同样,对于纯 PHP 区块类型,supports 数组必须包含 'auto_register' => true

According to Héctor Priethor,

除了简化自定义区块类型的创建并使其易于集成到混合主题中之外,纯 PHP 区块还可以用作旧版 PHP 函数和短代码的封装。此外,使用纯 PHP 区块为自定义集成和服务器端功能开辟了新的可能性。

Héctor Priethor 所述:

纯 PHP 注册模型将简化区块开发的最低要求,使其适用于更广泛的开发者群体,并有助于区块生态系统超越高级 JavaScript 的使用。

使用属性构建区块设置UI

PR 74102 实现了从区块属性定义自动生成检查器控件。这使得用户可以像配置任何通过 JavaScript 注册的 Gutenberg 区块一样配置纯 PHP 区块的外观和功能。

以前,您必须手动在 React 中创建一个 edit.js 文件,并使用 React 组件定义各种设置控件。

现在,Gutenberg 会读取属性定义,并在 WordPress 编辑器中自动生成相应的输入字段。

系统会将 attributes 数组中定义的数据类型映射到 DataForm 字段定义。

  • 'type' => 'string' 生成一个文本字段。
  • 'type' => 'number' 生成一个数字字段。
  • 'type' => 'integer' 会生成一个整数字段。
  • 'type' => 'boolean' 会生成一个复选框。
  • 'type' => 'string' 并结合 'enum' => array() 会生成一个下拉选择框。

你会发现你只能使用少数几种控件。如果你需要特定的控件,例如 RichTextRangeControl, 或 ToggleControl,你仍然需要选择使用 JS/React 来实现。

然而,这种新增功能也带来了显著的优势。它进一步降低了入门门槛,你无需学习 React、Webpack 或 NPM 即可创建带有简单可编辑选项的自定义区块。

在下面的示例中,我们通过添加一些属性来扩展上一节中显示的示例区块。

/**
* 1. Define the block's HTML output.
*/
function my_php_only_block_render( $attributes ) {
// Extract attributes
$title   = esc_html( $attributes['blockTitle'] );
$count   = intval( $attributes['itemCount'] );
$enabled = $attributes['isEnabled']; // Boolean from the ToggleControl
$size    = esc_attr( $attributes['displaySize'] );
// Start building the output
$output = sprintf( '<div class="my-php-block" style="font-size: %s; border: 1px solid #ccc; padding: 15px;">', 
$size === 'large' ? '20px' : ($size === 'small' ? '12px' : '16px') 
);
$output .= sprintf( '<h3>🚀 %s</h3>', $title );
// If the toggle is ON, show the list. If OFF, show a fallback message.
if ( $enabled ) {
$output .= '<ul>';
for ( $i = 1; $i <= $count; $i++ ) {
$output .= sprintf( '<li>Item %d</li>', $i );
}
$output .= '</ul>';
} else {
$output .= '<p><em>The list is currently disabled.</em></p>';
}
$output .= '</div>';
return $output;
}
/**
* 2. Register the block on 'init'.
*/
add_action( 'init', function() {
register_block_type( 'my-plugin/php-only-test-block', array(
'title'           => 'My PHP-only Block',
'icon'            => 'welcome-learn-more',
'category'        => 'text',
'render_callback' => 'my_php_only_block_render',
// Attributes used to generate the Inspector UI
'attributes'      => array(
'blockTitle'  => array(
'type'    => 'string',
'default' => 'PHP-only Block',
),
'itemCount'   => array(
'type'    => 'integer',
'default' => 3,
),
'isEnabled'   => array(
'type'    => 'boolean',
'default' => true,
),
'displaySize' => array(
'type'    => 'string',
'enum'    => array( 'small', 'medium', 'large' ),
'default' => 'medium',
),
),
'supports'        => array(
'auto_register' => true, 
),
) );
});

快速浏览这段代码即可发现,使用新的 API 注册自定义区块及其所有配置设置是多么简单。属性现在不仅用于存储用户输入的数据,还用于定义 UI 架构。上面的代码执行以下操作:

  • register_block_type 函数注册区块类型 my-plugin/php-only-test-block
  • 传递给该函数的第二个参数是一个数组,其中包含以下元素:titleiconcategoryrender_callbackattributes, 和 supports
  • attributes 数组包含区块的属性。在上面的示例中,该数组包含元素 blockTitleitemCountisEnabled, 和 displaySize
  • 'auto_register' => true 启用服务器端自动注册。

Here is what the callback function my_php_only_block_render does:

以下是回调函数 my_php_only_block_render 的工作原理:

  • 首先,该函数从 $attributes 数组中提取属性值,并将它们分别赋值给 $title$count$enabled, 和 $size 变量。
  • 然后,它生成区块的内容。

以下是屏幕上的显示结果:

一个纯 PHP 区块及其设置

一个纯 PHP 区块及其设置

纯PHP区块的实际应用示例

虽然在很多情况下仍然需要 JavaScript,但纯 PHP 区块已经可以实现很多功能,尤其是在使用区块属性时。

在下面的示例中,我们使用 get_block_wrapper_attributes() 函数,该函数会为当前渲染的区块生成一个属性字符串。区块会自动接收用户设置的颜色、边框和阴影,并将相应的样式应用到主容器。这样,就可以像使用 React 区块一样,通过 Gutenberg 的原生工具自定义区块。

要查看实际效果,请在您的计算机上创建一个名为 smart-pricing-widget 的文件夹。在该文件夹中,创建一个名为 style.css 的文件,并添加以下 CSS 代码:

/* style.css */
.pricing-card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
box-sizing: border-box;
}
.pricing-card h3 {
margin: 0;
font-size: 1.5rem;
}
.pricing-card .price-value {
font-size: 3.5rem;
font-weight: 800;
margin: 15px 0;
}
.pricing-card ul {
list-style: none;
padding: 25px 0;
margin: 20px 0;
width: 100%;
border-top: 1px solid rgba(128,128,128,0.3);
display: flex;
flex-direction: column;
gap: 12px;
}
.pricing-card li {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.pricing-card .cta-button {
margin-top: auto;
padding: 15px 25px;
border-radius: 8px;
text-decoration: none;
font-weight: bold;
transition: opacity 0.2s;
}
.pricing-card .cta-button:hover {
opacity: 0.8;
}
/* Theme Variations */
.pricing-card.theme-light { background-color: #ffffff; color: #000000; }
.pricing-card.theme-light .cta-button { background-color: #21759b; color: #ffffff; }
.pricing-card.theme-dark { background-color: #1a1a1a; color: #ffffff; }
.pricing-card.theme-dark .cta-button { background-color: #ffffff; color: #1a1a1a; }
.pricing-card.theme-blue { background-color: #21759b; color: #ffffff; }
.pricing-card.theme-blue .cta-button { background-color: #000000; color: #ffffff; }
/* Utility Classes */
.pricing-card .is-full-width {
width: 100%;
display: block;
align-self: stretch;
}

由于这只是一个简单的组件区块样式表,我们不会对此代码进行任何注释。

现在,创建插件的主文件,将其命名为 smart-pricing-widget.php,并将以下代码粘贴到该文件中:

<?php
/**
* Plugin Name: Smart Pricing Widget
* Plugin URI:  https://example.com/
* Description: PHP-only Pricing Table block
* Version:     1.2.0
* Author:      Your Name
* Text Domain: smart-pricing-widget
*/
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Render callback
*/
function render_smart_pricing_block( $attributes ) {
$plan_name = esc_html( $attributes['planName'] );
$price     = intval( $attributes['price'] );
$theme     = $attributes['blockTheme'];
$btn_text  = esc_html( $attributes['buttonText'] );
$btn_size  = $attributes['buttonSize'];
$features_raw = $attributes['featuresList'];
$features_array = array_filter( array_map( 'trim', explode( ',', $features_raw ) ) );
$wrapper_attributes = wp_kses_data( get_block_wrapper_attributes( array(
'class' => "pricing-card theme-{$theme}",
) ) );
$output = sprintf( '<div %s>', $wrapper_attributes );
$output .= sprintf( '<h3>%s</h3>', $plan_name );
$output .= sprintf( '<div class="price-value">€%d</div>', $price );
if ( ! empty( $features_array ) ) {
$output .= '<ul>';
foreach ( $features_array as $feature ) {
$is_checked = strpos( $feature, '+' ) === 0;
$clean_text = esc_html( ltrim( $feature, '+- ' ) );
$icon       = $is_checked ? '✅' : '❌';
$style      = $is_checked ? '' : 'style="opacity: 0.6;"';
$output .= sprintf( '<li %s><span>%s</span> %s</li>', $style, $icon, $clean_text );
}
$output .= '</ul>';
}
$btn_class = 'cta-button' . ( $btn_size === 'full' ? ' is-full-width' : '' );
$output .= sprintf( '<a href="#" class="%s">%s</a>', esc_attr( $btn_class ), $btn_text );
$output .= '</div>';
return $output;
}
/**
* Register Assets and Block
*/
add_action( 'init', function() {
// 1. Register the CSS file
wp_register_style(
'smart-pricing-style',
plugins_url( 'style.css', __FILE__ ),
array(),
'1.2.0'
);
// 2. Register the Block
register_block_type( 'tutorial/smart-pricing', array(
'api_version'     => 3,
'title'           => 'Pricing Card',
'icon'            => 'cart',
'category'        => 'widgets',
'render_callback' => 'render_smart_pricing_block',
// Link the registered style handle here
'style'           => 'smart-pricing-style',
'attributes'      => array(
'planName'     => array( 'type' => 'string', 'default' => 'Professional' ),
'price'        => array( 'type' => 'integer', 'default' => 49 ),
'buttonText'   => array( 'type' => 'string', 'default' => 'Choose Plan' ),
'buttonSize'   => array( 'type' => 'string', 'enum' => array( 'auto', 'full' ), 'default' => 'auto' ),
'blockTheme'   => array( 'type' => 'string', 'enum' => array( 'light', 'dark', 'blue' ), 'default' => 'light' ),
'featuresList' => array( 'type' => 'string', 'default' => "+ Support, + Updates, - Domain" ),
),
'supports'        => array(
'auto_register' => true,
'color'         => array( 'background' => true, 'text' => true ),
'spacing'       => array( 'margin' => true, 'padding' => true ),
'typography'    => array( 'fontSize' => true ),
'shadow'        => true,
'__experimentalBorder' => array( 'color' => true, 'radius' => true, 'style' => true, 'width' => true ),
'border'        => array( 'color' => true, 'radius' => true, 'style' => true, 'width' => true ),
),
) );
});

此脚本包含两个函数。register_block_type() 函数是插件的核心。以下是其主要组成部分:

  • 第一个参数是区块标识符,包含命名空间( tutorial/smart-pricing )。
  • 第二个参数是一个参数数组。在上面的代码中,我们设置了 API 版本、标题、图标、类别、渲染回调、样式、属性和支持
  • 数组中的属性生成用户用于添加内容和配置区块的控件。type 元素指定要添加到区块检查器的控件类型。在本例中,这些控件包括文本字段( 'type' => 'string' )、整数( 'type' => 'integer' )和几个下拉菜单( 'type' => 'string''enum' => 'array()' )。
  • supports 数组项添加了使区块样式可自定义的功能。如前所述,纯 PHP 区块唯一需要的支持是 auto_register,它能为自定义属性自动生成 UI。其他支持包括颜色、间距、字体、阴影和边框。

回调函数 render_smart_pricing_block() 会生成区块的 HTML 代码。以下是该函数的详细说明:

  • 它会提取并清理区块属性,然后添加 CSS 代码,从而在前端和编辑器中生成区块的外观。
  • 区块中要显示的功能列表($attributes['featuresList'];)是单独处理的。目前,无法在区块设置侧边栏添加高级控件。要创建列表(例如功能列表),您只能使用简单的文本字段。在本例中,您必须手动输入产品功能,并用逗号分隔。
  • $wrapper_attributes 变量用于存储 get_block_wrapper_attributes 函数提供的包装器属性。该函数不仅会添加代码中指定的类(pricing-card theme-{$theme}),还会自动检索用户在区块检查器中设置的所有样式自定义项,包括颜色、边框、内边距、外边距、阴影、字体以及标准区块类(wp-block-tutorial-smart-pricing)。
  • wp_kses_data 确保字符串中不包含恶意标签或脚本(XSS)。
  • 其余代码生成区块内容。

激活插件并创建一个新文章或页面。打开区块插入器并向下滚动到“小工具”部分。在这里,您应该可以看到带有购物车图标的“Pricing Card”区块。

自定义的纯 PHP 区块

自定义的纯 PHP 区块(位于区块编辑器中)

上图显示的是默认浅色主题下的区块。

下图显示的是深色主题下的区块,以及您在插件中设置的属性。

仅支持 PHP 的区块及其设置

仅支持 PHP 的区块及其设置

下图展示了您使用区块支持添加的样式控件。

仅使用 PHP 编写的区块的深色主题

仅使用 PHP 编写的区块的深色主题,支持自定义颜色

值得注意的是,支持人员添加的样式会覆盖区块主题样式。这使得区块外观可以进行更精细的自定义,如下图所示:

价格表

包含三个服务级别的价格表,每个级别对应三个 PHP 编写的区块实例

使用纯PHP将旧版短代码转换为古腾堡区块

PHP 区块最直接的用途之一是作为短代码封装器。在 Gutenberg 中,您仍然可以在内容中使用短代码,但必须手动将短代码插入到短代码区块中,这并非最佳体验。

假设您有以下短代码:

function my_custom_alert_shortcode( $atts ) {
$options = shortcode_atts( array(
'type'    => 'info',
'message' => 'Default alert message',
), $atts );
$styles = array(
'info'    => 'background: #d1ecf1; color: #0c5460; border-color: #bee5eb;',
'warning' => 'background: #fff3cd; color: #856404; border-color: #ffeeba;',
'error'   => 'background: #f8d7da; color: #721c24; border-color: #f5c6cb;'
);
$style = $styles[ $options['type'] ] ?? $styles['info'];
return sprintf(
'<div class="sc-alert-box" style="%s padding: 20px; border: 1px solid; border-radius: 6px; margin: 10px 0;">
<strong style="text-transform: uppercase;">%s:</strong> %s
</div>',
esc_attr( $style ),
esc_html( $options['type'] ),
esc_html( $options['message'] )
);
}
add_shortcode( 'sc_alert', 'my_custom_alert_shortcode' );

这段代码会生成一个简单的框,您可以使用以下短代码将其插入到您的内容中:

[sc_alert type="alert" message="Hello"]

在 Gutenberg 编辑器中,您可以使用简码区块将框插入到您的内容中,如下图所示:

短代码区块

短代码区块

使用纯 PHP 区块后,情况就完全不同了。现在,您可以将短代码封装在纯 PHP 古腾堡区块中,并通过 UI 控件进行配置。以下是需要添加到插件中的代码:

/**
* Rendering callback
*/
function render_shortcode_alert_wrapper_block( $attributes ) {
$type    = esc_attr( $attributes['alertType'] );
$message = esc_attr( $attributes['alertMessage'] );
$shortcode_string = sprintf( '[sc_alert type="%s" message="%s"]', $type, $message );
$wrapper_attributes = wp_kses_data( get_block_wrapper_attributes( array(
'class' => 'wp-block-shortcode-alert-wrapper',
) ) );
return sprintf(
'<div %s>%s</div>',
$wrapper_attributes,
do_shortcode( $shortcode_string )
);
}
/**
* Register the block type on the server
*/
add_action( 'init', function() {
register_block_type( 'tutorial/alert-wrapper', array(
'api_version'     => 3,
'title'           => 'Alert (Shortcode wrapper)',
'icon'            => 'feedback',
'category'        => 'widgets',
'render_callback' => 'render_shortcode_alert_wrapper_block',
'attributes'      => array(
'alertType' => array(
'type'    => 'string',
'enum'    => array( 'info', 'warning', 'error' ),
'default' => 'info',
),
'alertMessage' => array(
'type'    => 'string',
'default' => 'Type your alert message here...',
),
),
'supports'        => array(
'auto_register' => true,
'spacing'       => array( 'margin' => true, 'padding' => true ),
'typography'    => array( 'fontSize' => true ),
),
) );
});

上面的代码与上一节中的代码类似。不同之处在于渲染回调函数。

  • $shortcode_string 存储短代码字符串(例如 [sc_alert type="%s" message="%s"])。
  • 该函数返回包含短代码的区块容器的 HTML 代码(do_shortcode( $shortcode_string ))。

现在,打开区块插入器,在组件中找到“Shortcode wrapper”区块。将其插入到您的内容中,并在区块设置栏中进行配置。该区块在编辑器和前端的显示效果将完全相同。

用纯 PHP 区块封装的短代码示例

一个用纯 PHP 区块封装的短代码示例

纯PHP代码区块如何改变WordPress开发?

目前,纯 PHP 区块仍处于实验阶段,功能有限。Gutenberg 提供了更强大的功能,例如区块样板区块变体,它们提供了原生 Gutenberg 区块和用 JavaScript 构建的自定义区块的所有编辑功能。然而,在某些情况下,纯 PHP 区块也提供了重要的机遇。

首先,纯 PHP 区块应该能够促进区块编辑器的更广泛应用,尤其是在那些不太熟悉服务器端 JavaScript 开发的 WordPress 开发者中。

此外,它们是自定义函数和短代码的理想封装,正如本文示例所示。而且,它们还允许轻松地与外部服务集成。

我们还可以合理地期待未来的改进和功能添加,更多的配置控制以及与现有 Gutenberg 工具的集成。

有一点可以肯定:有了纯 PHP 区块,构建 Gutenberg 区块变得更加容易。

评论留言

闪电侠

(工作日 10:00 - 18:30 为您服务)

2026-04-16 02:40:54

您好,无论是售前、售后、意见建议……均可通过联系工单与我们取得联系。

您也可选择聊天工具与我们即时沟通或点击查看:

您的工单我们已经收到,我们将会尽快跟您联系!
取消
选择聊天工具: