Tạo block tùy chỉnh chỉ với PHP. Tạm biệt shortcode kiểu cũ 🥳
Xây dựng block Gutenberg đã đòi hỏi React, Node.js và một build pipeline kể từ khi WordPress 5.0 giới thiệu block editor. Nếu kỹ năng của bạn là PHP — như tôi và phần lớn các lập trình viên WordPress — rào cản đó đã giữ bạn đứng ngoài lề gần một thập kỷ. WordPress 7.0 thay đổi điều này. Block PHP-only cho phép bạn đăng ký một block Gutenberg hoạt động đầy đủ chỉ với một file PHP duy nhất và flag autoRegister.
Bạn viết PHP. Bạn có một block. Không cần tooling. Không cần build. 🥳 Trong bài viết này, bạn sẽ thấy cách block PHP-only hoạt động và đi qua một ví dụ thực tế thay thế shortcode cổ điển bằng block tương đương.
Block PHP-Only Là Gì?
Cho đến nay, xây dựng một block Gutenberg tùy chỉnh có nghĩa là phải thiết lập một toolchain JavaScript: npm install, một file block.json, một bước build với webpack.config.js hoặc @wordpress/scripts, và một component edit.js viết bằng JSX. Mỗi thay đổi yêu cầu một bước biên dịch trước khi bạn có thể thấy nó trong editor. Đối với một lập trình viên PHP chỉ muốn đăng ký một block hiển thị đơn giản, gánh nặng đó luôn có vẻ không tương xứng với nhiệm vụ.
Block PHP-only cắt giảm tất cả những điều đó. Bây giờ, trong register_block_type() bạn chỉ cần truyền 'autoRegister' => true, và WordPress tự động xử lý mọi thứ phía JavaScript bằng cách sử dụng ServerSideRender. Block xuất hiện trong inserter, hiển thị bản xem trước trực tiếp trên canvas, và tạo ra Inspector Controls trong sidebar — tất cả mà không cần một dòng JavaScript nào từ phía bạn.
Các control được tự động tạo dựa trên kiểu thuộc tính:
| Kiểu thuộc tính | Inspector Control được tạo |
|---|---|
string | Trường văn bản |
integer / number | Trường số |
boolean | Công tắc bật/tắt |
string + enum | Dropdown chọn |
Các control tự động tạo hiện chỉ bao gồm bốn kiểu trên. Bất cứ điều gì phức tạp hơn như bộ chọn hình ảnh, tải lên media, hay dữ liệu lồng nhau vẫn chưa được hỗ trợ và sẽ cần một block được đăng ký bằng JavaScript. Các lập trình viên cũng có thể đánh dấu từng thuộc tính với vai trò local để đánh dấu chúng là trạng thái nội bộ; WordPress bỏ qua chúng khi xây dựng các control trên sidebar.
Block PHP-only đã có sẵn ngay hôm nay trong WordPress 7.0 mà không cần bất kỳ phụ thuộc bổ sung nào. Đọc thêm trong ghi chú chính thức dành cho lập trình viên trên Make WordPress Core.
Dành Cho Ai?
Các agency nhỏ và freelancer không có chuyên môn sâu về JavaScript hiện có thể xây dựng các giải pháp block editor tận dụng đầy đủ các tính năng gốc của WordPress mà không cần chạm vào build pipeline. Nếu bạn muốn tạo ra các block Gutenberg tùy chỉnh dành riêng cho theme như hộp thông tin tác giả, trích dẫn nổi bật, lời chứng thực, banner CTA, thông báo và các phần tử tương tự thay vì dùng shortcode, block PHP-only giúp hạ thấp đáng kể rào cản đó.
Chúng không phải là sự thay thế cho block đăng ký bằng JavaScript khi bạn cần chỉnh sửa văn bản phong phú trực tiếp trên canvas, giao diện phản hồi thời gian thực, hay lồng block bên trong — nhưng đối với một nhóm lớn các block hiển thị có cấu trúc, chúng đáp ứng hoàn toàn nhu cầu.
Cách Cũ: Shortcode
Trước khi có block PHP-only, cách tiếp cận thực tế của lập trình viên PHP là dùng shortcode. Đây là một shortcode lời chứng thực đơn giản với ba thuộc tính: tên tác giả, công ty, đánh giá sao, cộng với nội dung bên trong cho văn bản đánh giá:
function testimonial_shortcode( $atts, $content = '' ) {
$atts = shortcode_atts( [
'name' => '',
'company' => '',
'stars' => 5,
], $atts );
$stars_count = max( 1, min( 5, intval( $atts['stars'] ) ) );
$stars_html = str_repeat( '★', $stars_count )
. str_repeat( '☆', 5 - $stars_count );
return sprintf(
'<blockquote class="testimonial">
<p class="testimonial__stars">%s</p>
<p class="testimonial__body">%s</p>
<footer class="testimonial__attribution">
<strong>%s</strong>%s
</footer>
</blockquote>',
esc_html( $stars_html ),
wp_kses_post( $content ),
esc_html( $atts['name'] ),
$atts['company'] ? ', ' . esc_html( $atts['company'] ) : ''
);
}
add_shortcode( 'testimonial', 'testimonial_shortcode' );Cách dùng:
[testimonial name="Sarah K." company="Acme Corp" stars="4"]
Saved us hours every week.
[/testimonial]Nó hoạt động... nhưng chỉ là một shortcode thôi 🤷🏻♂️
Đây chỉ là một số vấn đề với shortcode:
- Vô hình trong editor. Tác giả nhìn thấy
[testimonial name="Sarah K." ...]trong editor, không phải thẻ đã được render. Không có bản xem trước. - Khó khám phá. Bạn phải biết shortcode tồn tại và nhớ tên các tham số của nó. Không có gì hiển thị nó trong giao diện.
- Không có control style gốc. Điều chỉnh màu sắc, khoảng cách, hay typography đòi hỏi CSS tùy chỉnh hoặc các thuộc tính bổ sung được kết nối thủ công.
- Nội dung bên trong không phải văn bản phong phú. Phần nội dung đánh giá được truyền qua như một chuỗi đơn giản trong
$content— không phải là vùng văn bản phong phú có thể chỉnh sửa.
Shortcode là công cụ phù hợp cho thời đại của chúng. Block editor cung cấp điều gì đó tốt hơn, nhưng đã khó để tận dụng. WordPress 7.0 cung cấp lối tắt dưới dạng block PHP-only.
Để rõ ràng: cách đúng đắn mới để xây dựng một block Gutenberg vẫn là một block được đăng ký bằng JavaScript với một component edit đầy đủ. Block PHP-only là một con đường đơn giản hóa — được cố tình giới hạn cho các block render phía server mà không cần chỉnh sửa phong phú trực tiếp trên canvas. Chúng không phải là sự thay thế cho block JavaScript, mà là một lựa chọn mới cho các trường hợp sử dụng đơn giản hơn khi gánh nặng của build pipeline và các component React không được biện minh.
Lựa Chọn Đơn Giản Hơn: Block PHP-Only
Hãy xây dựng cùng một lời chứng thực như một block tùy chỉnh WordPress chỉ với PHP. Công thức: register_block_type() với 'autoRegister' => true trong supports, cộng với render_callback.
Đây là code đầy đủ cho block:
function my_plugin_register_testimonial_block() {
register_block_type(
'my-plugin/testimonial', // Block name: namespace/slug
array(
'title' => 'Testimonial', // Shown in the block inserter
'attributes' => array(
// string attributes generate a text input in the sidebar
'name' => array(
'type' => 'string',
'default' => '',
),
'company' => array(
'type' => 'string',
'default' => '',
),
// integer attributes generate a number input
'stars' => array(
'type' => 'integer',
'default' => 5,
),
'body' => array(
'type' => 'string',
'default' => '',
),
),
// render_callback is the PHP function that outputs the block's HTML
'render_callback' => function ( $attributes ) {
$stars_count = max( 1, min( 5, intval( $attributes['stars'] ) ) );
$stars_html = str_repeat( '★', $stars_count )
. str_repeat( '☆', 5 - $stars_count );
// Translatable string for screen readers — standard WordPress i18n, nothing extra needed
/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );
return sprintf(
'<blockquote %s>
<p class="testimonial__stars" aria-label="%s">%s</p>
<p class="testimonial__body">%s</p>
<cite class="testimonial__attribution">
<strong>%s</strong>%s
</cite>
</blockquote>',
// Merges your class with editor-added colour, spacing, and typography styles
get_block_wrapper_attributes( array( 'class' => 'testimonial wp-block-quote' ) ),
esc_attr( $stars_label ),
esc_html( $stars_html ),
wp_kses_post( $attributes['body'] ),
esc_html( $attributes['name'] ),
$attributes['company'] ? ', ' . esc_html( $attributes['company'] ) : ''
);
},
'supports' => array(
// The key flag — tells WordPress to handle JS registration automatically
'autoRegister' => true,
// The rest unlock native colour, typography, and spacing panels in the sidebar
'color' => array(
'background' => true,
'text' => true,
),
'typography' => array(
'fontSize' => true,
),
'spacing' => array(
'padding' => true,
'margin' => true,
),
),
)
);
}
add_action( 'init', 'my_plugin_register_testimonial_block' );Kết quả:

Có một số điều cần lưu ý ở đây. Thứ nhất, nội dung bên trong của shortcode không có tương đương trực tiếp trong block PHP-only. Phần nội dung đánh giá trở thành một thuộc tính string được chỉnh sửa từ Inspector Controls trên sidebar — một trường văn bản một dòng, không phải vùng văn bản phong phú trên canvas. Đối với một trích dẫn lời chứng thực ngắn thì điều này ổn. Đối với nội dung dài hơn, bạn sẽ muốn một block được đăng ký bằng JavaScript với component RichText.
Thứ hai, get_block_wrapper_attributes() kết hợp class của bạn với bất cứ thứ gì editor thêm vào cho màu sắc, typography và khoảng cách — vì vậy các panel style gốc hoạt động mà không cần kết nối CSS bổ sung. render_callback nhận một mảng $attributes chỉ chứa các giá trị mà người dùng đã đặt; không có tham số $content, vì nội dung bên trong không được hỗ trợ.
Những gì bạn có được so với phiên bản shortcode:
- Bản xem trước trực tiếp trên canvas editor. Không còn cú pháp shortcode thô — tác giả nhìn thấy thẻ lời chứng thực được render khi họ chỉnh sửa.
- Control tự động tạo. Tên, công ty, nội dung (trường văn bản) và sao (trường số) tự động xuất hiện trong Inspector Controls trên sidebar.
- Panel màu sắc, font và khoảng cách gốc. Đến từ
supports— không cần CSS tùy chỉnh. - Dễ khám phá. Block xuất hiện trong inserter dưới tên của nó, với biểu tượng.
Sẵn Sàng Dịch Thuật Ngay Từ Đầu
Có hai mối quan tâm dịch thuật riêng biệt khi làm việc với block PHP-only, và đáng để làm rõ cái nào là cái nào.
Thứ nhất là các chuỗi tĩnh được đặt cứng trong template PHP của bạn — nhãn, văn bản nút, văn bản giao diện. Chúng được xử lý bởi __() và _e(), giống như trong bất kỳ file PHP WordPress nào. Trong block ở trên, nhãn sao là một ví dụ:
/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );Các công cụ WordPress tiêu chuẩn tự động phát hiện những chuỗi này. Không cần gì thêm.
Mối quan tâm thứ hai là nội dung do người dùng nhập được lưu trữ dưới dạng thuộc tính block — nội dung lời chứng thực, tên người đánh giá, công ty. Đây là nội dung mà các biên tập viên của bạn thực sự gõ vào block, và __() không chạm đến nó. Trên một trang web đa ngôn ngữ, các giá trị thuộc tính này cần được dịch sang từng ngôn ngữ riêng biệt, và đó không phải là điều WordPress tự xử lý.
Gato AI Translations for Polylang hỗ trợ block PHP-only ngay từ đầu, giống như cách nó hỗ trợ Gutenberg, Bricks, Elementor và các page builder khác. Không cần thiết lập thêm.
Tất cả các thuộc tính string đều được tự động đăng ký để dịch. Nếu một trường cụ thể không nên được dịch — một tham chiếu nội bộ, một URL, một mã số được lưu trữ dưới dạng chuỗi — bạn có thể loại trừ nó bằng một filter.
Đối với block lời chứng thực trong bài viết này, tên người đánh giá, công ty và văn bản nội dung đều được dịch tự động — không cần cấu hình gì ngoài việc cài đặt plugin.
Những Gì Block PHP-Only Chưa Làm Được
Các giới hạn hiện tại của block PHP-only:
- Không có block bên trong hay lồng nhau. Bạn không thể thả các block khác vào bên trong một block PHP-only.
- Không có chỉnh sửa văn bản phong phú trên canvas. Component
RichTextyêu cầu JavaScript. Các control văn bản chỉ hiển thị như một trường văn bản trên sidebar. - Các trường chuỗi trên sidebar là một dòng. Một thuộc tính
stringtrở thànhTextControl, không phảiTextareaControl— không lý tưởng cho nội dung dài hơn. - Không có thuộc tính bộ chọn hình ảnh hay media. Hỗ trợ tải lên hình ảnh/file được lên kế hoạch cho bản phát hành sau thông qua Block Fields API.
- Bản xem trước editor có độ trễ khứ hồi. Thay đổi thuộc tính kích hoạt một yêu cầu REST API để render lại trên server, vì vậy bản xem trước không cập nhật ngay lập tức.
Đối với các block có cấu trúc đơn giản — lời chứng thực, CTA, thông báo, tiểu sử tác giả, danh sách doanh nghiệp — block PHP-only đáp ứng hoàn toàn. Đối với bất cứ điều gì yêu cầu chỉnh sửa phong phú trực tiếp trên canvas, đăng ký bằng JavaScript vẫn là công cụ phù hợp.
Tiếp Theo Là Gì
Block PHP-only của WordPress 7.0 đưa việc phát triển block đến tầm tay của bất kỳ lập trình viên PHP nào. Một file PHP, một lần gọi register_block_type(), và bạn có một block Gutenberg hoạt động đầy đủ với các control trên sidebar, bản xem trước trực tiếp trên canvas, và hỗ trợ style gốc. Bạn viết PHP. Bạn có một block. Không cần tooling. Không cần build. Không cần JavaScript.
Nếu bạn đang xây dựng các trang web đa ngôn ngữ, Gato AI Translations hoạt động liền mạch với block PHP-only — nội dung của bạn có thể dịch được ngay từ ngày đầu tiên.
Sẵn sàng để tiến xa hơn?
- Developing WordPress blocks without JSX or a build process — dành cho các lập trình viên muốn thêm JavaScript tối thiểu mà không cần build pipeline đầy đủ
- Beginner WordPress Developer course — nền tảng hoàn chỉnh cho việc phát triển block