如何構建純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 開發者採用區塊編輯器的一大障礙,因為他們可能缺乏必要的 React 和 Node.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。
  • 區塊型別的引數陣列。在上面的程式碼中,我們設定了 title, icon, category, render_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() 會生成一個下拉選擇框。

你會發現你只能使用少數幾種控制元件。如果你需要特定的控制元件,例如 RichText, RangeControl, 或 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。
  • 傳遞給該函式的第二個引數是一個陣列,其中包含以下元素:title, icon, category, render_callback, attributes, 和 supports。
  • attributes 陣列包含區塊的屬性。在上面的示例中,該陣列包含元素 blockTitle, itemCount, isEnabled, 和 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 區塊變得更加容易。

評論留言