يا هلا بيك يا صديقي في واحد من أهم مفترقات الطرق الهندسية في رحلة احتراف تطوير ووردبريس ومحرر المكونات Gutenberg. أول ما تبدأ تبني بلوك جديد، أول سؤال هندسي لازم تسأله لنفسك ومش تسيبه للصدفة هو: “يا ترى البلوك ده أخليه بلوك ثابت (Static Block) ولا بلوك ديناميكي (Dynamic Block)؟”.
القرار ده مش مجرد تفضيل شخصي أو رفاهية برمجية؛ ده قرار بيحدد مصير موقعك بالكامل من حيث سرعة الأداء (Performance)، استهلاك السيرفر، مرونة التحديثات المستقبلية، وقبل كل ده: الأمان ضد كابوس Block Invalidation Error الشهير اللي ممكن يصحيك الصبح يلاقي آلاف المقالات ضاربة في وش المحررين! في المقال ده، هنشرح الفروق المعمارية الجوهرية بين النوعين، إزاي تختار “مصدر الحقيقة الوحيد” (Single Source of Truth – SSOT)، إزاي تبني النوعين بكود إنتاجي مع ملف render.php الحديث، وهندرس معمارية الهجين (Hybrid Architecture) وحالة عملية حقيقية من السوق المصري بالعامية المصرية التقنية الأصيلة.
| المعيار المعماري | البلوكات الثابتة (Static Blocks) | البلوكات الديناميكية (Dynamic Blocks) | المعمارية الهجينة (Hybrid Blocks) |
|---|---|---|---|
| ماذا يُخزن في قاعدة البيانات؟ | الـ HTML الكامل المولد مسبقاً مع تعليق البلوك وخصائصه في post_content. | تعليق البلوك وحزم البيانات (JSON Attributes) فقط بدون كود HTML جاهز. | هيكل HTML هيكلي ثابت (Shell) مع سمات بيانات (Data Attributes) للترطيب. |
| دالة الحفظ في JavaScript (save.js) | تُرجع كود JSX كامل يترجم إلى عناصر HTML دلالية حقيقية. | تُرجع null صراحة (أو <InnerBlocks.Content /> فقط). | تُرجع الـ Markup المبدئي اللازم لمحركات البحث (SEO Fallback). |
| طريقة العرض في الواجهة الأمامية | المتصفح يقرأ الـ HTML المحفوظ في قاعدة البيانات مباشرة وبسرعة فائقة. | السيرفر يعالج كود PHP لحظياً (SSR) عبر render.php قبل الإرسال. | السيرفر يرسل الـ Shell ثم تقوم مكتبة React/JS بترطيبه في المتصفح. |
| مخاطر تلف البلوك (Block Invalidation) | عالية جداً إذا تغير الـ HTML في الكود دون كتابة قواعد Deprecation. | منعدمة تماماً (صفر) لأن الـ HTML لا يُقارن بقاعدة البيانات إطلاقاً. | منخفضة إلى متوسطة بحسب ثبات هيكل الـ Shell المولد. |
| القدرة على عرض بيانات حية ولحظية | شبه مستحيلة بدون إعادة حفظ كل مقال يدوياً من جديد. | ممتازة وطبيعية؛ تقرأ الأسعار، المنتجات، والتواريخ لحظة بلحظة. | مثالية للواجهات التفاعلية كالسلات التفاعلية وحسابات المستخدمين. |
| استهلاك معالج السيرفر (CPU Overhead) | شبه معدوم؛ نصوص ثابتة يتم تخزينها وتمريرها عبر الـ Page Cache. | يتطلب تنفيذ كود PHP واستعلامات DB (يتطلب Transients/Redis Cache). | معالجة خفيفة على السيرفر ونقل العبء التفاعلي لمتصفح الزائر. |
معمارية مصدر الحقيقة الوحيد (Single Source of Truth – SSOT)
عشان تفهم الفلسفة وراء التقسيم ده، تعال نبص على السؤال الفلسفي في علوم هندسة البرمجيات: أين يكمن مصدر الحقيقة للبيانات (Where does truth live)?
1. في البلوكات الثابتة (Static Blocks): “المقال هو الحقيقة”
تخيل إنك بتكتب مقال عادي فيه فقرة نصية (Paragraph) أو اقتباس (Quote). المقال ده مش معتمد على أي بيانات خارجية في الموقع. الكلام اللي كتبته في المحرر هو هو اللي المفروض الزائر يشوفه النهاردة وبكرة وبعد سنة. هنا الـ HTML الناتج هو الحقيقة!
لما المحرر يضغط “نشر” (Publish)، محرر جوتنبرج بيشغل دالة save()، يحول الـ JSX لكود HTML خام، ويحطه جوة جدول wp_posts. ميزة الحركة دي إيه؟
- أداء خارق للعادة: لما الزائر يطلب الصفحة، ووردبريس مش محتاج يشغل دوال معقدة ولا يعمل استعلامات إضافية على قاعدة البيانات؛ السيرفر بيقذف الـ HTML للمتصفح فوراً، ولو عندك موديول كاش زي WP Rocket أو LiteSpeed أو Cloudflare، الصفحة بتتسلم من الرام في أجزاء من الألف من الثانية!
- استقلالية تامة عن الـ PHP: حتى لو قفلت البلجن اللي عمل البلوك بعد سنة، المحتوى هيفضل ظاهر في الصفحة زي الفل ومش هيختفي لأن الـ HTML خلاص اتطبع في جسم المقال.
2. في البلوكات الديناميكية (Dynamic Blocks): “قاعدة البيانات هي الحقيقة الحية”
تخيل بقى سيناريو مختلف تماماً: بتعمل بلوك يعرض “أحدث 5 مقالات” أو “سعر جرام الذهب عيار 21 اليوم في السوق المصري” أو “بيانات كارت المنتج وسعره بالجنيه في ووكومرس”.
لو استخدمت هنا بلوك ثابت، الـ HTML هيتحفظ بسعر الذهب النهاردة (وليكن 3,800 جنيه). بكرة السعر بقى 3,900 جنيه؛ المقال هيفضل عارض 3,800 لأن الـ HTML اتجمد في قاعدة البيانات خلاص! عشان يتحدث، هتضطر تفتح 500 مقال وتدوس “Update” يدوياً!
هنا بنقول: الـ HTML مش هو الحقيقة، ده “البيانات الخارجية اللحظية” هي الحقيقة! وبالتالي دالة save() في الجافاسكريبت بترجع null، ومفيش أي كود HTML بيتخزن في جسم المقال؛ اللي بيتخزن هو تعليق كده:
<!-- wp:market/gold-price {"karat":21,"showChart":true} /-->
ولما الزائر يفتح الصفحة، ووردبريس بيشوف التعليق ده ويقول: “أها! البلوك ده ديناميكي، استنى لما استدعي ملف render.php عشان يجيب السعر اللحظي من قاعدة البيانات أو الـ API، ويعمل Render للـ HTML ويرسله للزائر طازة!”.
تطبيق عملي كامل: بناء البلوكين جنباً إلى جنب
تعال نبني مثالين حقيقيين عشان تشوف الفرق بالسطر والرمز، وكيف تنفذ المعماريتين باحترافية كاملة وفق معايير apiVersion: 3 الحديثة.
أولاً: بناء البلوك الثابت (Static Testimonial Block)
بلوك آراء العملاء؛ نصوص واقتباسات ثابتة يكتبها المحرر ولا تتغير لحظياً.
1. ملف block.json للبلوك الثابت
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "enterprise/static-testimonial",
"version": "1.0.0",
"title": "رأي العميل الثابت",
"category": "text",
"icon": "format-quote",
"attributes": {
"quote": {
"type": "string",
"source": "html",
"selector": ".az-quote-text"
},
"author": {
"type": "string",
"source": "text",
"selector": ".az-author-name"
},
"role": {
"type": "string",
"default": "عميل موثق"
}
},
"editorScript": "file:./index.js",
"style": "file:./style-index.css"
}2. كود edit.js للبلوك الثابت
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
export default function Edit( { attributes, setAttributes } ) {
const { quote, author, role } = attributes;
const blockProps = useBlockProps( { className: 'az-testimonial-box' } );
return (
setAttributes( { quote: val } ) }
placeholder={ __( 'اكتب شهادة أو رأي العميل هنا...', 'az-blocks' ) }
/>
setAttributes( { author: val } ) }
placeholder={ __( 'اسم العميل...', 'az-blocks' ) }
/>
( { role } )
);
}3. كود save.js للبلوك الثابت
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const { quote, author, role } = attributes;
const blockProps = useBlockProps.save( { className: 'az-testimonial-box' } );
return (
( { role } )
);
}
لاحظ هنا: دالة save رجعت كود JSX كامل، وتم استخدام RichText.Content لحفظ الـ HTML في قاعدة البيانات. لو قمت مستقبلاً بتغيير وسم <cite> إلى <footer> دون كتابة Deprecation، فإن ووردبريس سيرفض البلوك ويعتبره تالفاً!
ثانياً: بناء البلوك الديناميكي (Dynamic Product Pricing Block)
بلوك يعرض السعر اللحظي لمنتج معين مع التوفر في المخزن مباشرة من قاعدة البيانات.
1. ملف block.json للبلوك الديناميكي
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "enterprise/dynamic-pricing-card",
"version": "1.0.0",
"title": "بطاقة السعر اللحظي الديناميكية",
"category": "widgets",
"icon": "cart",
"attributes": {
"productId": {
"type": "number",
"default": 0
},
"showStockStatus": {
"type": "boolean",
"default": true
}
},
"render": "file:./render.php",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}2. كود edit.js للبلوك الديناميكي
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, TextControl, ToggleControl, Spinner } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
export default function Edit( { attributes, setAttributes } ) {
const { productId, showStockStatus } = attributes;
const blockProps = useBlockProps( { className: 'az-pricing-card-preview' } );
// جلب بيانات المنتج الحية داخل شاشة التحرير لمعاينة شكل البلوك للمحرر
const { product, isResolving } = useSelect( ( select ) => {
if ( ! productId ) return { product: null, isResolving: false };
const { getEntityRecord, isResolving: resolving } = select( 'core' );
return {
product: getEntityRecord( 'postType', 'product', productId ),
isResolving: resolving( 'getEntityRecord', [ 'postType', 'product', productId ] )
};
}, [ productId ] );
return (
setAttributes( { productId: parseInt( val, 10 ) || 0 } ) }
help={ __( 'أدخل الرقم التعريفي للمنتج في ووكومرس', 'az-blocks' ) }
/>
setAttributes( { showStockStatus: val } ) }
/>
{ __( 'معاينة بطاقة السعر الديناميكية (Live SSR)', 'az-blocks' ) }
{ isResolving && }
{ ! isResolving && product && (
{ product.title?.rendered || __( 'منتج بدون اسم', 'az-blocks' ) }
{ __( 'السعر الحالي: ', 'az-blocks' ) }
{ product.meta?._price || '0.00' } ج.م
) }
{ ! isResolving && ! product && (
{ __( 'الرجاء إدخال معرف منتج صالح في الشريط الجانبي.', 'az-blocks' ) }
) }
);
}3. كود save.js للبلوك الديناميكي: القفل الآمن
/**
* في البلوك الديناميكي: دالة save ترجع null دائماً!
* لا يتم حفظ أي وسم HTML في قاعدة البيانات، مما يضمن حصانة مطلقة ضد أخطاء Invalidation.
*/
export default function save() {
return null;
}4. كود ملف السيرفر: render.php المحصن بالتخزين المؤقت (Transients Caching)
<?php
/**
* ملف render.php لبلوك كارت السعر الديناميكي
*
* @var array $attributes خصائص البلوك المخزنة
* @var string $content المحتوى الداخلي (فارغ في هذا النمط)
* @var WP_Block $block كائن البلوك
*/
$product_id = isset( $attributes['productId'] ) ? absint( $attributes['productId'] ) : 0;
$show_stock = ! empty( $attributes['showStockStatus'] );
if ( ! $product_id ) {
return; // لا تطبع شيئاً في الواجهة الأمامية إذا لم يحدد المنتج
}
// مفتاح كاش ذكي لتفادي الضغط على قاعدة البيانات في الصفحات كثيفة الزيارات
$cache_key = 'az_dyn_product_' . $product_id;
$card_data = get_transient( $cache_key );
if ( false === $card_data ) {
// جلب بيانات ووكومرس بأمان
if ( ! function_exists( 'wc_get_product' ) ) {
return;
}
$product = wc_get_product( $product_id );
if ( ! $product || ! $product->is_visible() ) {
return;
}
$card_data = [
'name' => $product->get_name(),
'price_html'=> $product->get_price_html(),
'in_stock' => $product->is_in_stock(),
'stock_qty' => $product->get_stock_quantity(),
'permalink' => $product->get_permalink(),
];
// تخزين مؤقت لمدة 10 دقائق فقط لتسريع التصفح مع الحفاظ على حداثة السعر
set_transient( $cache_key, $card_data, 10 * MINUTE_IN_SECONDS );
}
$wrapper_attributes = get_block_wrapper_attributes( [
'class' => 'az-dynamic-pricing-card-wrapper',
] );
?>
<aside <?php echo $wrapper_attributes; ?>>
<div class="az-dynamic-card-header">
<h4 class="az-product-title">
<a href="<?php echo esc_url( $card_data['permalink'] ); ?>">
<?php echo esc_html( $card_data['name'] ); ?>
</a>
</h4>
</div>
<div class="az-dynamic-card-body">
<div class="az-price-tag">
<?php echo wp_kses_post( $card_data['price_html'] ); ?>
</div>
<?php if ( $show_stock ) : ?>
<div class="az-stock-status <?php echo $card_data['in_stock'] ? 'is-in-stock' : 'is-out-of-stock'; ?>">
<?php if ( $card_data['in_stock'] ) : ?>
<span class="az-badge-available"><?php esc_html_e( 'متوفر في المخزن والشحن فوري', 'az-blocks' ); ?></span>
<?php else : ?>
<span class="az-badge-unavailable"><?php esc_html_e( 'نفد من المخزن مؤقتاً', 'az-blocks' ); ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<div class="az-dynamic-card-footer">
<a href="<?php echo esc_url( $card_data['permalink'] ); ?>" class="az-btn-order">
<?php esc_html_e( 'شراء الآن بالسعر المحدث', 'az-blocks' ); ?>
</a>
</div>
</aside>دراسة حالة واقعية: أزمة متجر السوبر ماركت وتطبيق طلبات البقالة في القاهرة الكبرى
خلفية المشروع وأبعاد الأزمة
منصة إلكترونية ضخمة لتوصيل طلبات البقالة ومستلزمات الطبخ في القاهرة والجيزة، تمتلك مدونة طهي ومحتوى تسويقي ضخمة تضم أكثر من 2,500 وصفة طبخ (“طريقة عمل الكبسة”، “مقادير الملوخية بالفراخ”، إلخ). في نهاية كل وصفة، كان الفريق يضع كارت بلوك يحتوي على “شراء مقادير الوصفة بضغطة واحدة” مع تفاصيل أسعار الزيت والسكر والدواجن.
الأزمة التشخيصية (The Crisis)
المطور السابق قام ببناء البلوك كـ بلوك ثابت (Static Block) يخزن اسم المكون وسعره بالجنيه المصري داخل كود الـ HTML المحفوظ في كل مقال:
- مع التغيرات السريعة في أسعار السلع في السوق المصري خلال عام 2023-2024، تغيرت أسعار زيت الذرة والدواجن والسمن أسبوعياً.
- المدونة ظلت تعرض أسعاراً قديمة جداً (مثلاً: زجاجة الزيت بـ 45 جنيه في المقال، بينما سعرها الفعلي في المتجر وصل لـ 80 جنيه)!
- العملاء اعتبروا الأمر “تضليلاً تجارياً”، وتلقت خدمة العملاء أكثر من 400 شكوى أسبوعية، مع مطالبات بتعويضات واضطرار الفريق لتحمل فروق الأسعار لتجنب فقدان ثقة العملاء.
- عندما حاول فريق التطوير عمل سكربت لتحديث نصوص المقالات برمجياً في قاعدة البيانات، تسبب ذلك في انهيار الـ Blocks وصدور أخطاء Validation Error دمرت مظهر 1,800 مقال بالكامل!
الحل المعماري الجذري (The Architectural Solution)
قام الفريق الهندسي بإعادة هيكلة البلوك معمارياً من الصفر:
- تحويل البلوك بالكامل إلى Dynamic Block، حيث لا يخزن المقال سوى معرف السلعة (Product SKU / ID) فقط، مع جعل
save() { return null; }. - استخدام ملف
render.phpليقوم بجلب السعر اللحظي مباشرة من قاعدة بيانات ووكومرس المركزية لحظة طلب الزائر للصفحة. - تطبيق معمارية Transient Invalidation Hook: كلما قام مدير المتجر بتغيير سعر سلعة في لوحة تحكم WooCommerce، يقوم خطاف
save_post_productبحذف كاش الترانزينت المرتبط بالمنتج فوراً، مما يضمن ظهور السعر الجديد في كافة مقالات الوصفات البالغ عددها 2,500 مقال في نفس الثانية بدون فتح أي مقال منهم!
جدول قياس مؤشرات الأداء والتحول المالي (Metrics Table)
| مؤشر الأداء والتشغيل | الوضع قبل الحل (البلوك الثابت) | الوضع بعد الحل (البلوك الديناميكي الكاشد) | القيمة المضافة والأثر الفعلي |
|---|---|---|---|
| زمن تحديث أسعار المقالات عند تغير السوق | 3 أسابيع من التعديل اليدوي العقيم | 0.00 ثانية (تحديث لحظي مركزي) | تحول فوري بنسبة 100% لبيانات حية |
| أخطاء شكاوى الأسعار وخدمة العملاء | 412 شكوى أسبوعياً وخسائر تعويض | صفر شكاوى لأسعار غير مطابقة | حماية سمعة العلامة التجارية ووقف النزيف |
| سلامة المقالات من أخطاء الـ Validation | تعطل 1,800 مقال وظهور أخطاء كسر | صفر أخطاء تلف؛ حصانة مطلقة | أمان كامل عند تحديث كود القالب والبلجن |
| معدل استهلاك المعالج وتأثير الكاش (Hit Ratio) | معالجة بطيئة وعشوائية | 98.6% معدل إصابة الكاش (Redis/Transients) | زمن استجابة السيرفر أقل من 120ms |
الوصايا العشر لاختيار المعمارية المناسبة بين البلوكات الثابتة والديناميكية
- طبق قاعدة الشك: هل البيانات تتغير بمرور الوقت؟ لو الإجابة نعم (سعر، مخزون، عدد متابعين، أحدث منشورات)، اجعل البلوك ديناميكياً فوراً بلا تردد.
- البلوك الثابت للمحتوى التحريري الصرف: المقالات، الاقتباسات، العناوين، وبلوكات التصميم الهيكلي البحت هي المرشح المثالي للبلوكات الثابتة لتوفير أداء فائق.
- في البلوك الديناميكي: save() ترجع null دائماً: لا تضع وسوماً إضافية في الجافاسكريبت حتى لا تقع في فخ المقارنة العقيمة في محرر Gutenberg.
- اعتمد على render.php بدلاً من render_callback: استخدام ملف منفصل في
block.jsonأنظف معمارياً، يسهل اختبار الكود، ويفصل العرض عن منطق التسجيل. - لا تشغل استعلامات SQL ثقيلة بدون Transients: البلوك الديناميكي قد يُطلب ملايين المرات يومياً؛ خزّن نتائج العمليات الحسابية في كاش مؤقت دائماً.
- اربط حذف الكاش بـ Hooks التحديث: عند تغيير البيانات المصدرية، احذف الـ Transient فوراً لضمان عدم ظهور بيانات قديمة للمستخدمين.
- وفر معاينة حية في شاشة التحرير: لا تجعل المحرر يرى مربعاً أسود أو نصاً جافاً؛ استخدم
getEntityRecordداخلedit.jsليشاهد البلوك كما سيظهر بالضبط. - اهرب من الـ Invalidation في الثابت بكتابة Deprecations: إذا اضطررت لتغيير بنية الـ HTML في بلوك ثابت منشور، اكتب قواعد الترحيل في مصفوفة
deprecatedفوراً. - استخدم esc_html و wp_kses دائماً في السيرفر: مجرد أن البلوك مبرمج بواسطة فريقك لا يعفيك من تعقيم كل متغير يُطبع داخل ملف
render.php. - وثق قرارك المعماري في الـ Readme: اذكر سبب اختيار النمط الثابت أو الديناميكي في توثيق المشروع ليفهم زملاؤك في الفريق الفلسفة وراء المعمارية.
الأسئلة الشائعة حول البلوكات الثابتة والديناميكية (20 سؤالاً وجواباً تفصيلياً)
1. متى يجب عليّ قطعاً استخدام بلوك ديناميكي (Dynamic Block)؟
عندما تعتمد محتويات البلوك على بيانات حية تتغير من قاعدة البيانات أو أطراف خارجية دون تعديل المقال نفسه، مثل أسعار المنتجات، حالة الطقس، أحدث المقالات، أو بيانات المستخدم المسجل.
2. ما هو السبب الرئيسي لحدوث خطأ Block Invalidation في البلوكات الثابتة؟
يحدث عندما يختلف كود الـ HTML الذي تنتجه دالة save() في الكود المحدث عن كود الـ HTML المسجل مسبقاً في قاعدة بيانات المقال، حتى لو كان الاختلاف مسافة بيضاء أو إضافة كلاس بسيط.
3. لماذا ترجع دالة save() القيمة null في البلوكات الديناميكية؟
لتخبر محرر ووردبريس بألا يحفظ أي كود HTML في قاعدة البيانات، مما يعفي البلوك تماماً من عمليات التحقق والمقارنة عند فتح المقال مجدداً في المحرر.
4. هل تؤثر البلوكات الديناميكية سلباً على سرعة الموقع؟
إذا بُنيت بدون كاش، نعم قد تزيد زمن معالجة السيرفر (TTFB). ولكن مع استخدام أنظمة التخزين المؤقت مثل Transients و Redis و Page Caching، يصبح الفارق شبه معدوم.
5. كيف أجمع بين InnerBlocks والبلوك الديناميكي؟
في دالة save() ترجع <InnerBlocks.Content /> فقط، وفي ملف render.php تستقبل الـ HTML للأبناء وتطبعه عبر المتغير $content داخل الحاوية السيرفرية.
6. ما هو الفرق بين render_callback وملف render.php في block.json؟
كلاهما يؤدي نفس الوظيفة السيرفرية، لكن render.php هو النمط القياسي الحديث المنفصل الذي يدعم التحميل الكسول والعزل النظيف لملفات القالب دون الحاجة لحشو ملفات الـ PHP بدوال مجهولة.
7. هل يمكن تحويل بلوك ثابت موجود في آلاف المقالات إلى بلوك ديناميكي؟
نعم، عن طريق إفراغ دالة save لترجع null وإضافة render.php، مع إضافة البنية القديمة في مصفوفة deprecated حتى يتعامل معها المحرر بسلاسة دون أخطاء.
8. كيف يرى محرك البحث (Googlebot) محتوى البلوك الديناميكي؟
يراه ككود HTML كامل ونظيف تماماً؛ لأن ووردبريس يقوم بمعالجة الـ PHP وإنتاج الـ HTML قبل إرسال الاستجابة للزائر أو لعناكب البحث عبر السيرفر (SSR).
9. ما هي أفضل استراتيجية لتخزين كاش البلوكات الديناميكية؟
استخدام دالة set_transient مع مفتاح فريد يحتوي على معرف العنصر، وربط حذف الكاش بـ Action Hooks مثل save_post أو woocommerce_update_product لضمان التحديث الفوري.
10. أين تُخزن خصائص (Attributes) البلوك الديناميكي إذا كان الـ HTML لا يُخزن؟
تُخزن ككائن JSON مشفر داخل تعليق فتح البلوك في عمود post_content، مثل: <!-- wp:my/block {"id":5} /-->.
11. هل يمكن استخدام خطافات React في ملف render.php؟
لا طبعاً؛ ملف render.php يعمل بالكامل على خادم الـ PHP في بيئة السيرفر، بينما خطافات React تعمل في متصفح العميل (Client Browser) داخل ملفات الـ JS.
12. ماذا يحدث لمحتوى البلوك الثابت إذا تم تعطيل البلجن المطور له؟
يظل المحتوى ظاهراً للمستخدمين وعناكب البحث دون تغيير، لأن كود الـ HTML أصبح جزءاً أصيلاً ومحفوظاً من نص المقال في قاعدة البيانات.
13. ماذا يحدث لمحتوى البلوك الديناميكي إذا تم تعطيل البلجن المطور له؟
يختفي المحتوى من الواجهة الأمامية تماماً، لأن ووردبريس لن يجد ملف render.php لتنفيذه وسيتجاهل تعليق البلوك في الـ HTML.
14. هل البلوكات الثابتة تدعم التخصيص التلقائي لكل مستخدم (Personalization)؟
لا؛ البلوك الثابت يعرض نفس المحتوى الحرفي لكافة الزوار، بينما البلوك الديناميكي يمكنه فحص هوية الزائر (Logged-in user) وعرض محتوى مخصص له.
15. كيف أضمن ظهور معاينة دقيقة للبلوك الديناميكي داخل محرر جوتنبرج؟
باستخدام كومبوننت ServerSideRender أو خطافات useSelect مع core-data لجلب وتنسيق البيانات الحية في شاشة التحرير بنفس كلاسات العرض الحقيقية.
16. ما هي دالة get_block_wrapper_attributes() وما أهميتها في البلوك الديناميكي؟
هي دالة PHP حيوية تولد كافة الكلاسات والأنماط المعرفة من ووردبريس (مثل الألوان والهوامش وفئات المحاذاة)، ويجب دائماً طباعتها على الغلاف الخارجي للبلوك في render.php.
17. هل يمكن أن يكون البلوك الواحد ثابتاً وديناميكياً في نفس الوقت؟
نعم؛ يسمى ذلك بالبلوك الهجين (Hybrid Block)، حيث يُخزن هيكل ثابت في قاعدة البيانات بينما يتم ترطيب بعض أجزائه التفاعلية عبر JavaScript أو Dynamic Endpoints.
18. أيهما أسهل في الصيانة طويلة المدى للمشاريع الضخمة؟
البلوكات الديناميكية أسهل بكثير في الصيانة الهيكلية؛ لأن أي تعديل في الـ HTML ينعكس فوراً على آلاف المقالات السابقة بمجرد تعديل سطر واحد في render.php.
19. كيف أمنع استدعاء ملف render.php في خلاصات الـ RSS أو الـ REST API إذا أردت؟
يمكنك فحص السياق عبر دوال ووردبريس مثل is_feed() أو التحقق من ثوابت الـ REST API وتجاوز الطباعة أو إرجاع ملخص نصي بديل.
20. ما هي النصحة الذهبية لمهندسي ووردبريس عند بدء أي بلوك جديد؟
“اجعل الثابت قاعدتك الافتراضية للسرعة، والديناميكي اختيارك الحتمي للتفاعل والبيانات المتغيرة”؛ لا تفرط في أحدهما على حساب الآخر.
المراجع الرسمية والتوثيق المعتمد
- WordPress Developer Handbook: Creating Dynamic Blocks
- WordPress Block API Reference: Metadata and render.php Template
- WordPress Developer Reference: get_block_wrapper_attributes Function
- WordPress Developer APIs: Transients API for High-Performance Caching
- Gutenberg Core Architectural Key Concepts on GitHub


اترك تعليقاً
يجب أنت تكون مسجل الدخول لتضيف تعليقاً.