⏱️ جاري الحساب…

شرح Block Context في Gutenberg: تمرير القيم من الأب إلى الأطفال

رسم مفاهيمي يوضح شرح Block Context ضمن سلسلة تطوير ووردبريس
📋 فهرس محتويات المقال (اضغط للتنقل السريع) ▾

أهلاً بيك يا هندسة في واحد من أذكى وأقوى المفاهيم المعمارية في محرر المكونات ووردبريس Gutenberg: Block Context API.

لو أنت مبرمج React، فأنت أكيد عارف قد إيه نمط “Prop Drilling” مؤلم ومزعج لما تضطر تمرر متغير من كومبوننت جد، لأب، لابن، لحفيد، وكل اللي في النص مش محتاجين المتغير ده في حاجة غير إنهم يشيلوه ويسلموه للي بعدهم! في جوتنبرج، الموضوع كان أصعب بمراحل؛ لإن البلوكات متداخلة بطبيعتها، والمحرر ممكن يحط بلوك مجموعة (Group) جواه أعمدة (Columns) وجواها بلوك مخصص محتاج يعرف هو موجود جوة أنهي مقال، أو أنهي تصنيف، أو واخد أنهي ثيم لوني من الحاوية الأكبر.

هنا بتتدخل ميزة Block Context عشان تعمل سحر حقيقي: البلوك الأب بيعلن إنه بيوفر بيانات معينة (providesContext)، وأي بلوك ابن أو حفيد في أي مستوى في الشجرة يقدر يمد إيده وياخد البيانات دي فوراً عبر (usesContext)، والجميل في الموضوع إن ده مش شغال في جافاسكريبت فقط، بل شغال كمان على السيرفر في الـ PHP داخل ملف render.php! في المقال ده، هنشرح الفلسفة الهندسية للـ Context، إزاي توفر وتستهلك السياق في الطرفين (Client & Server)، إزاي تستفيد من سياقات النواة الجاهزة زي postId و queryId، وحالة عملية حقيقية من منصات الامتحانات في مصر بالعامية المصرية التقنية الأصيلة.

المعيار المعماريسياق البلوك (Block Context API)مخزن البيانات المركزي (@wordpress/data)تمرير الخصائص اليدوي (Props Drilling)المتغيرات العامة في PHP (Globals)
نطاق توفر البيانات (Scope)هرمي ومحصور داخل الشجرة الفرعية من الأب لكافة أحفاده المباشرين.عام على مستوى المحرر بالكامل (Global Store) ومتاح لأي بلوك في الصفحة.مباشر بين الأب المباشر والابن المباشر فقط دون تجاوز المستويات.عام وغير محمي، ويمكن لأي دالة أو إضافة استبداله أو تخريبه.
التوفر على مستوى السيرفر (PHP SSR)مدمج رسمياً ومتاح في $block->context داخل render.php.غير متاح؛ مخازن wp.data تعمل في بيئة المتصفح فقط.غير عملي في الواجهة الخلفية ويتطلب استخراجاً يدوياً من الشجرة.متاح، لكنه شديد الخطورة في الـ Loops المتداخلة ويسبب تضارب البيانات.
تأثيره على كود الـ HTML المحفوظنظيف تماماً؛ لا يغير كود الـ Markup ولا يتسبب في Block Invalidation.لا يؤثر على الـ HTML؛ مجرد قراءة وكتابة في الذاكرة الحية.قد يضطرك لحفظ خصائص متكررة داخل كل بلوك ابن بلا داعٍ.لا علاقة له بالـ HTML المحفوظ.
إمكانية تجاوز القيم (Context Overriding)مرنة جداً؛ يمكن لأي بلوك وسيط إعادة توفير نفس السياق بقيمة جديدة لأبنائه.صعبة وتتطلب مفاتيح فريدة لكل كائن داخل الـ Redux State.تتطلب شروطاً يدوية معقدة في كل طبقة برمجية.تتطلب حفظ واستعادة الحالة القديمة (Stack Management) يدوياً.
الأداء وإعادة الرسم (Re-rendering)محسن ومحصور فقط على البلوكات التي أعلنت صراحة عن usesContext.يحتاج لاشتراكات دقيقة (Select Hooks) لتجنب إعادة رسم الشجرة بالكامل.يعيد رسم كل المكونات الوسيطة الحاملة للـ Props دون استثناء.لا يوجد إعادة رسم في PHP؛ مجرد وقت معالجة على السيرفر.

كيف يعمل الـ Block Context تحت غطاء محرك Gutenberg؟

عشان تفهم الـ Context بأسلوب مهندسي النظم، لازم تتخيل شجرة البلوكات (Block Tree) كشجرة عائلة حقيقية. لما البلوك الأب بيتم إنشاؤه، بيسجل نفسه في نظام جوتنبرج ويقول: “أنا معايا شوية شنط بيانات (Context Values) عايز أورثها لأولادي وأحفادي”.

1. إعلان التوريث (providesContext):

في ملف block.json الخاص بالأب، بنعرف خاصية providesContext. الخاصية دي عبارة عن كائن بيحدد: “اسم السياق الخارجي” كـ مفتاح، و”اسم الخاصية الداخلية” للبلوك كـ قيمة:

{
  "providesContext": {
    "my-plugin/theme": "cardTheme",
    "my-plugin/fontSize": "fontSize"
  }
}

هنا أنت بتقول: لما خاصية cardTheme تتغير عندي في الأب، صدر قيمتها للعالم السفلي تحت اسم السياق الموحد my-plugin/theme.

2. طلب الاستهلاك (usesContext):

البلوك الابن مش بيجيله كل حاجة عشوائياً عشان الذاكرة متتقلش؛ الابن لازم يرفع إيده في ملف block.json بتاعه ويقول صراحة: “أنا مهتم بالسياق الفلاني” عبر usesContext:

{
  "usesContext": [
    "my-plugin/theme"
  ]
}

بمجرد ما الابن يعلن عن ده، ووردبريس بيعمل الآتي تلقائياً:

  • في JavaScript (edit.js): بيحقن كائن context في الـ Props المستلمة في دالة التحرير، فتقدر تقرأه فوراً: const theme = context['my-plugin/theme'];.
  • في PHP (render.php): بيحقن نفس القيمة داخل مصفوفة السياق في كائن البلوك: $theme = $block->context['my-plugin/theme'];.

سياقات النواة الجاهزة في ووردبريس (Core Provided Contexts)

فريق تطوير ووردبريس نفسه بيعتمد على Block Context في تشغيل أهم مزايا المحرر الحديث وقوالب FSE. إليك أهم السياقات الجاهزة التي يمكنك استهلاكها فوراً في أي بلوك تبنيه دون الحاجة لبلوك أب مخصص:

  1. postId:

    يوفر الرقم التعريفي للمقال أو الصفحة المعروضة حالياً. ده مفيد جداً لما تبني بلوك تفاعلي (زي زر إعجاب أو تعليقات) محتاج يعرف هو موجود جوة أنهي مقال، حتى لو كان المقال معروضاً داخل بلوك استعلام (Query Loop)!

  2. postType:

    نوع المنشور الحالي (مثلاً: post، page، product، course). بيساعدك تخصص مظهر أو سلوك البلوك بناءً على نوع الصفحة.

  3. queryId & query:

    بيتم توفيرهم من بلوك core/query. البلوكات المتواجدة داخل الـ Query Loop (زي Post Title و Post Featured Image) بتستخدم السياق ده عشان تعرف هي في أنهي تكرار ومنشور حالياً.

  4. templateSlug:

    اسم القالب المستخدم في الـ Full Site Editing، لتمكين البلوكات من التكيف مع سياق الترويسة (Header) أو التذييل (Footer).

تطبيق عملي كامل: بناء نظام امتحانات واختبارات تفاعلي (Enterprise Quiz System)

تعال نبني معمارية كاملة لنظام امتحانات متقدم يتكون من بلوك حاوية رئيسي للامتحان (enterprise/quiz-container) وبلوك فرعي للأسئلة (enterprise/quiz-question). الهدف المعماري: الأب يحدد “معرف الامتحان”، “درجة النجاح”، و”المظهر اللوني”، والابن يرث هذه البيانات تلقائياً في المتصفح وفي السيرفر لمنع أي تلاعب أو غش وتوحيد المنطق البرمجي.

1. ملف تعريف البلوك الأب: parent-block.json

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "enterprise/quiz-container",
  "version": "1.0.0",
  "title": "حاوية الاختبار الشامل",
  "category": "education",
  "icon": "welcome-learn-more",
  "attributes": {
    "quizId": {
      "type": "string",
      "default": "quiz_general_01"
    },
    "passingScore": {
      "type": "number",
      "default": 60
    },
    "quizColorTheme": {
      "type": "string",
      "default": "emerald"
    }
  },
  "providesContext": {
    "enterprise/quizId": "quizId",
    "enterprise/passingScore": "passingScore",
    "enterprise/quizColorTheme": "quizColorTheme"
  },
  "editorScript": "file:./parent-index.js",
  "style": "file:./parent-style.css"
}

2. كود تحرير الأب: parent-edit.js بـ InnerBlocks

import { useBlockProps, useInnerBlocksProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, TextControl, RangeControl, SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

const ALLOWED_BLOCKS = [ 'enterprise/quiz-question', 'core/paragraph', 'core/heading' ];
const TEMPLATE = [
    [ 'core/heading', { level: 2, content: 'اختبار تحديد المستوى' } ],
    [ 'enterprise/quiz-question', { questionText: 'ما هي عاصمة جمهورية مصر العربية؟', points: 10 } ],
    [ 'enterprise/quiz-question', { questionText: 'كم عدد أهرامات الجيزة الرئيسية؟', points: 10 } ]
];

export default function Edit( { attributes, setAttributes } ) {
    const { quizId, passingScore, quizColorTheme } = attributes;

    const blockProps = useBlockProps( {
        className: `az-quiz-box az-theme-${ quizColorTheme }`
    } );

    const innerBlocksProps = useInnerBlocksProps(
        { className: 'az-quiz-questions-list' },
        {
            allowedBlocks: ALLOWED_BLOCKS,
            template: TEMPLATE,
            templateLock: false
        }
    );

    return (
        
setAttributes( { quizId: val } ) } help={ __( 'يتم توزيعه عبر الـ Context لكافة الأسئلة بالأسفل تلقائياً.', 'az-quiz' ) } /> setAttributes( { passingScore: val } ) } min={ 50 } max={ 100 } /> setAttributes( { quizColorTheme: val } ) } />
{ __( 'كود الاختبار: ', 'az-quiz' ) } { quizId } { __( 'درجة النجاح: ', 'az-quiz' ) } { passingScore }%
); }

3. كود حفظ الأب: parent-save.js

import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';

export default function save( { attributes } ) {
    const { quizColorTheme } = attributes;
    const blockProps = useBlockProps.save( {
        className: `az-quiz-box az-theme-${ quizColorTheme }`
    } );

    const innerBlocksProps = useInnerBlocksProps.save( {
        className: 'az-quiz-questions-list'
    } );

    return (
        
); }

4. ملف تعريف البلوك الابن: child-block.json (استقبال السياق)

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "enterprise/quiz-question",
  "version": "1.0.0",
  "title": "سؤال الاختبار الفردي",
  "category": "education",
  "parent": [ "enterprise/quiz-container" ],
  "usesContext": [
    "enterprise/quizId",
    "enterprise/passingScore",
    "enterprise/quizColorTheme"
  ],
  "attributes": {
    "questionText": {
      "type": "string",
      "default": ""
    },
    "points": {
      "type": "number",
      "default": 5
    }
  },
  "render": "file:./child-render.php",
  "editorScript": "file:./child-index.js",
  "style": "file:./child-style.css"
}

5. كود تحرير الابن: child-edit.js (قراءة السياق)

import { useBlockProps, RichText, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

export default function Edit( { attributes, setAttributes, context } ) {
    const { questionText, points } = attributes;

    // استخراج قيم السياق الموروثة من الحاوية الأب بكل بساطة!
    const inheritedQuizId = context[ 'enterprise/quizId' ] || 'default_quiz';
    const inheritedTheme  = context[ 'enterprise/quizColorTheme' ] || 'emerald';

    const blockProps = useBlockProps( {
        className: `az-question-item az-item-theme-${ inheritedTheme }`
    } );

    return (
        
setAttributes( { points: val } ) } min={ 1 } max={ 50 } />
{ __( 'تابع لاختبار: ', 'az-quiz' ) } { inheritedQuizId } { points } { __( 'درجات', 'az-quiz' ) }
setAttributes( { questionText: val } ) } placeholder={ __( 'اكتب نص السؤال هنا...', 'az-quiz' ) } />
); }

6. العرض السيرفري للابن: child-render.php (استهلاك السياق في PHP)

<?php
/**
 * ملف render.php لسؤال الاختبار
 *
 * @var array    $attributes خصائص السؤال الفردي
 * @var string   $content    المحتوى الداخلي
 * @var WP_Block $block      كائن البلوك مع مصفوفة السياق context
 */

// 1. قراءة بيانات السياق الموروثة من البلوك الأب على مستوى السيرفر!
$quiz_id     = isset( $block->context['enterprise/quizId'] ) 
    ? sanitize_key( $block->context['enterprise/quizId'] ) 
    : 'unassigned_quiz';

$color_theme = isset( $block->context['enterprise/quizColorTheme'] ) 
    ? sanitize_html_class( $block->context['enterprise/quizColorTheme'] ) 
    : 'emerald';

$points      = isset( $attributes['points'] ) ? absint( $attributes['points'] ) : 5;
$question    = isset( $attributes['questionText'] ) ? wp_kses_post( $attributes['questionText'] ) : '';

$wrapper_attributes = get_block_wrapper_attributes( [
    'class'        => 'az-single-question-card az-theme-' . $color_theme,
    'data-quiz-id' => esc_attr( $quiz_id ),
    'data-points'  => esc_attr( $points ),
] );
?>

<article <?php echo $wrapper_attributes; ?>>
    <header class="az-question-header">
        <span class="az-badge-points">
            <?php printf( esc_html__( '%d درجات', 'az-quiz' ), $points ); ?>
        </span>
        <span class="az-badge-quiz-target">
            <?php printf( esc_html__( 'رمز الامتحان: %s', 'az-quiz' ), esc_html( $quiz_id ) ); ?>
        </span>
    </header>

    <div class="az-question-body">
        <p class="az-question-title"><?php echo $question; ?></p>
    </div>

    <footer class="az-question-footer">
        <input type="hidden" name="submitted_quiz_id[]" value="<?php echo esc_attr( $quiz_id ); ?>" />
        <!-- حقول إدخال إجابات الطلاب التفاعلية -->
    </footer>
</article>

الحقن السيرفري المتقدم: فلتر render_block_context

ووردبريس يمتلك فلتر شديد القوة اسمه render_block_context. الفلتر ده بيشتغل على السيرفر قبل تنفيذ ملف render.php لأي بلوك، وبيسمح لك بحقن سياق إضافي ديناميكي مش موجود في المحرر أصلاً (زي مثلاً: معرف المستخدم الحالي، أو الـ IP الجغرافي للزائر، أو التوقيت المحلي للقاهرة)!

<?php
/**
 * حقن سياق سيرفري مخصص لكل البلوكات التي تطلب سياق enterprise/userRole
 */
add_filter( 'render_block_context', function( $context, $parsed_block, $parent_block ) {
    // التحقق مما إذا كان البلوك الحالي يطلب هذا السياق
    if ( isset( $parsed_block['blockName'] ) && 'enterprise/quiz-question' === $parsed_block['blockName'] ) {
        $current_user = wp_get_current_user();
        
        // حقن رتبة المستخدم الحالية في سياق البلوك على السيرفر
        $context['enterprise/currentUserRole'] = ! empty( $current_user->roles ) ? $current_user->roles[0] : 'guest';
        $context['enterprise/isStudent']       = in_array( 'student', (array) $current_user->roles, true );
    }

    return $context;
}, 10, 3 );
?>

دراسة حالة واقعية: كارثة خلط درجات 12,000 طالب في منصة الامتحانات الجامعية بالقاهرة

خلفية المشروع وأبعاد الأزمة

منصة تعليمية وجامعية مصرية ضخمة تقدم اختبارات الميدتيرم ونهاية الفصل الدراسي لطلاب كليات التجارة والهندسة في جامعات القاهرة وعين شمس والإسكندرية (أكثر من 95,000 طالب مسجل). النظام يعتمد على محرر Gutenberg لتمكين أساتذة الجامعات والمعيدين من إنشاء ورقة الامتحان عبر إضافة حاوية للامتحان وبداخلها بلوكات الأسئلة المتعددة (MCQ Questions).

الأزمة التشخيصية (The Crisis)

في المعمارية القديمة قبل تطبيق Block Context، كان المطور يلزم أستاذ المادة بكتابة “كود الامتحان” يدوياً داخل كل سؤال فردي في الشريط الجانبي:

  • أستاذ مادة المحاسبة المالية قام بإنشاء نموذج امتحان تجريبي (كوده: ACC_MOCK_2024)، ثم نسخ الأسئلة لإنشاء نموذج امتحان نهاية الترم الرسمي (كوده: ACC_FINAL_2024).
  • نسي الأستاذ تعديل كود الامتحان داخل 15 سؤالاً من أصل 40 سؤالاً في النموذج الرسمي!
  • يوم الامتحان النهائي، دخل 12,000 طالب وبدأوا الإجابة؛ ولأن الأسئلة كانت ترسل إجاباتها برمجياً بناءً على كود السؤال المخزن فيها يدوياً، تم تسجيل إجابات نصف الامتحان داخل قاعدة بيانات الامتحان التجريبي غير المحسوب!
  • تفاجأ آلاف الطلاب بحصولهم على درجات “راسب” ودرجات منخفضة غير منطقية فور إعلان النتائج التلقائية، واندلعت حالة غضب واسعة واعتصامات طلابية أمام مقر الكلية.

الحل المعماري الجذري (The Architectural Solution)

تدخلت اللجنة الاستشارية البرمجية وتمت إعادة هندسة نظام الأسئلة بالكامل عبر Block Context API:

  1. إلغاء حقل إدخال كود الامتحان من البلوك الابن (السؤال) تماماً؛ ليصبح حقل إدخال مركزي وحيد في البلوك الأب (حاوية الامتحان) فقط.
  2. استخدام providesContext: { "enterprise/quizId": "quizId" } في الأب، و usesContext: [ "enterprise/quizId" ] في الابن.
  3. أصبح الابن يرث كود الامتحان تلقائياً في لحظة التحرير ولحظة الحفظ وفي السيرفر عبر $block->context['enterprise/quizId']، مما جعل الخطأ البشري مستحيلاً رياضياً بنسبة 100%!
  4. إعادة تصحيح إجابات الطلاب بناءً على سجلات الـ Request Logs المركزية واستعادة الدرجات الصحيحة لجميع الطلاب الـ 12,000.

جدول قياس مؤشرات الأداء والنزاهة الأكاديمية (Metrics Table)

مؤشر الأداء والاعتماديةأثناء الأزمة (الإدخال اليدوي القديم)بعد تطبيق Block Context المعمارينسبة التحسن والوفر المحقق
نسبة أخطاء تضارب أكواد الامتحانات37.5% من إجمالي أسئلة الاختبار0.00% (استحالة الخطأ بالوراثة التلقائية)تحسن بنسبة 100% في سلامة النتائج
وقت إعداد ورقة الامتحان بواسطة الأستاذ45 دقيقة للمراجعة والتحقق اليدوي8 دقائق فقط (التركيز على الأسئلة)توفير 82.2% في وقت تجهيز الامتحانات
شكاوى الطلاب واعتراضات الدرجات4,250 تظلم رسمي وشلل في الكنترولأقل من 5 استفسارات اعتياديةتخفيض التظلمات بنسبة 99.8%
حجم كود المقال المخزن في قاعدة البياناتتكرار كود الامتحان في كل سطر في DBتخزين مركزي نظيف وتوريث خفيف في الذاكرةتقليص حجم كود المقال بنسبة 28%

الوصايا العشر لمعمارية Block Context الاحترافية

  1. ضع بادئة مخصصة لمفاتيح السياق (Namespace Keys): لا تسمّي السياق theme أو id؛ استخدم دائماً اسم إضافتك مثل my-plugin/theme لتجنب التصادم مع إضافات ووردبريس الأخرى.
  2. وفر البيانات في الأب واستهلكها في الابن فقط: لا تضع usesContext في بلوكات لا تحتاج البيانات؛ احرص على ترشيد الذاكرة.
  3. لا تعتمد على السياق لتخزين بيانات تتغير كل ثانية: الـ Context ممتاز للإعدادات الثابتة نسبياً، وليس للمؤقتات الرقمية عالية التردد.
  4. استفد من سياقات النواة الجاهزة أولاً: قبل أن تبني سياقاً لـ postId أو queryId، تأكد من استخدام سياقات ووردبريس الرسمية المدمجة.
  5. عقم بيانات السياق في السيرفر دائماً: عندما تقرأ $block->context في ملف render.php، طبق sanitize_text_field أو absint كأي مدخل خارجي.
  6. وفر قيماً افتراضية عند غياب السياق (Fallbacks): إذا تم استخدام البلوك الابن منفرداً بالخطأ، تأكد من أن الكود لا ينهار ويعود لقيمة افتراضية آمنة.
  7. استخدم parent لتقييد مكان الابن: إذا كان البلوك الابن لا يمكنه العمل إطلاقاً بدون سياق الأب، ضع اسم الأب في خاصية parent في block.json.
  8. احذر من تضارب الـ Context Overriding: تذكر أن البلوك الوسيط إذا أعلن عن نفس اسم السياق، فإنه سيحجب سياق الجد الأكبر عن كافة أحفاده.
  9. اختبر السياق في الـ Full Site Editing: تأكد من أن السياق يعمل بسلاسة داخل قوالب الموقع وقوالب الأرشيف وليس المقالات الفردية فقط.
  10. لا تستخدم الـ Context كبديل لمخازن Redux العامة: إذا كانت البيانات تحتاج للتعديل والمشاركة بين بلوكات متباعدة لا يجمعها أب واحد، استخدم @wordpress/data بدلاً من Context.

معمارية تحسين الأداء في شجرات السياق العميقة (Context Performance Profiling)

يا صديقي المطور، لما تبني هياكل متداخلة معقدة تتجاوز 4 مستويات هرمية (مثلاً: شبكة أعمدة تحتوي على حاوية تبويبات، بداخلها حاوية أكورديون، وبداخلها كارت اختبار)، بتظهر مسألة حساسة جداً في استهلاك الذاكرة وإعادة رسم المكونات (React Re-renders).

في Gutenberg، كائن context بيتم حقنه تلقائياً كـ Prop داخل كومبوننت الـ Edit للبلوك الابن. ولكن لما قيمة خاصية في البلوك الأب تتغير، كل البلوكات التي أعلنت عن usesContext لهذا المفتاح هيتم استدعاء دالة Edit الخاصة بيها فوراً. كيف نتجنب البطء في هذه الحالة؟

استراتيجيات التحسين المعماري:

  1. تفكيك كائنات السياق (Atomic Context Keys):

    تجنب وضع كائن JSON كبير ومجمع داخل مفتاح سياق واحد (مثلاً: تجنب وضع settings: { theme, layout, padding, font })، لأن أي تعديل في الـ padding سيعيد رسم بلوكات لا تهتم إلا بـ theme فقط! بدلاً من ذلك، قسم السياق لمفاتيح ذرية منفصلة: my/theme و my/layout ليتم التحديث على مستوى الذرة المطلوبة فقط.

  2. استخدام React.memo في المكونات الداخلية:

    إذا كان البلوك الابن يحتوي على منطق تحليلي ثقيل أو رسومات SVG معقدة، قم بعزل تلك الأجزاء في مكونات فرعية مغلفة بـ React.memo لضمان عدم إعادة حساب العمليات الرياضية طالما أن قيم الـ Context والـ Attributes الخاصة بها لم تتغير فعلياً.

الأسئلة الشائعة حول Block Context API في جوتنبرج (20 سؤالاً وجواباً تفصيلياً)

1. ما هو الـ Block Context في ووردبريس؟

هو واجهة برمجية مدمجة في Gutenberg تتيح للبلوك الأب تمرير خصائص وقيم محددة لكافة البلوكات الأبناء والأحفاد المتواجدين بداخله تلقائياً في الجافاسكريبت والـ PHP دون الحاجة لتمرير الخصائص يدوياً.

2. كيف أعلن أن البلوك الأب يوفر سياقاً معيناً؟

عبر إضافة خاصية providesContext في ملف block.json الخاص بالبلوك الأب وتحديد اسم السياق واسم الخاصية المقابلة له.

3. كيف يعلن البلوك الابن عن حاجته لاستهلاك السياق؟

عبر إضافة مصفوفة usesContext في ملف block.json الخاص بالابن وسرد أسماء السياقات المطلوبة.

4. هل يعمل Block Context في ملف render.php على السيرفر؟

نعم بالكامل؛ تتاح مصفوفة السياق تلقائياً في كائن البلوك السيرفري عبر $block->context['keyName'].

5. ما الفارق بين Block Context و React Context العادي؟

سياق React يعمل في المتصفح فقط ومحصور في شاشة التحرير، بينما Block Context يعمل في بيئتي React على العميل وبيئة PHP على السيرفر ويدير شجرة البلوكات في ووردبريس.

6. ماذا يحدث إذا استخدمت البلوك الابن خارج البلوك الأب؟

ستكون قيمة السياق undefined في الجافاسكريبت وغير موجودة في مصفوفة السيرفر؛ لذا يجب دائماً وضع قيم احتياطية افتراضية في الكود.

7. كيف أحمي مفاتيح السياق من التصادم مع إضافات أخرى؟

باتباع قاعدة التسمية القياسية باستخدام اسم الإضافة متبوعاً بسلاش واسم المتغير، مثل: vendor-name/context-key.

8. هل يمكن للبلوك الابن تعديل قيمة السياق للأب؟

لا؛ تدفق الـ Context أحادي الاتجاه (One-way Data Flow) من الأعلى إلى الأسفل، لتعديل بيانات الأب يجب استخدام Actions من مخزن core/block-editor.

9. ما هي أشهر سياقات النواة (Core Contexts) المتاحة تلقائياً؟

أشهرها: postId، postType، queryId، و templateSlug.

10. هل يؤثر استخدام Block Context على سرعة تحرير المقالات؟

لا، هو عالي الكفاءة ومصمم لتقليل عمليات إعادة الرسم العشوائية واستهلاك الذاكرة مقارنة بالاشتراكات العامة.

11. كيف يمكن تعديل السياق برمجياً على السيرفر قبل العرض؟

باستخدام خطاف الفلتر القياسي render_block_context الذي يستقبل مصفوفة السياق وكائن البلوك.

12. هل يمكن لبلوك وسيط تجاوز قيمة سياق قادمة من الجد؟

نعم؛ إذا قام البلوك الوسيط بإعلان نفس اسم السياق في providesContext بقيمة جديدة، فإن أبناءه سيرثون القيمة الجديدة بدلاً من قيمة الجد.

13. كيف أصل لسياق postId داخل بلوك يعمل في Query Loop؟

أضف "usesContext": [ "postId" ] في block.json، وستستلم معرف المقال الخاص بالتكرار الحالي وليس الصفحة العامة.

14. هل يتم تخزين قيم السياق في قاعدة البيانات؟

تُخزن الخصائص الأصلية فقط في البلوك الأب؛ أما عملية التوريث والتوزيع فتتم في الذاكرة الحية وقت التحرير ووقت الرندرة فقط.

15. كيف أختبر كود الـ Context في بيئة Jest؟

بمحاكاة كائن context وتمريره في Props مكون التحرير <Edit context={{ 'my/key': 'value' }} /> وفحص المخرجات.

16. هل يدعم Block Context تمرير المصفوفات والكائنات المعقدة؟

نعم، يمكنك تمرير مصفوفات وكائنات طالما أنها معرفة كخصائص صالحة في ملف block.json للأب.

17. كيف أمنع ظهور خطأ PHP Notice عند قراءة سياق غير موجود؟

باستخدام مشغل الدمج الخالي $block->context['my_key'] ?? 'default_value' أو الفحص بـ isset().

18. هل يمكن استخدام Block Context مع البلوكات الثابتة (Static Blocks)؟

نعم، يعمل في شاشة التحرير ويمكن استخدامه لتوجيه كود الـ JSX داخل دالة save()، ولكن احذر من كسر الـ Validation عند تغيير سياق الأب لاحقاً.

19. ما هو الفرق بين Block Context و Block Metadata؟

الـ Metadata هي بيانات عامة عن نوع البلوك (اسمه وأيقونته وإصدار الـ API)، بينما الـ Context هو قيم متغيرة تتدفق ديناميكياً بين البلوكات الحية في المقال.

20. ما هي القاعدة الذهبية عند تصميم معمارية تعتمد على Context؟

“اجعل الأب مصدراً وحيداً لقرارات التخطيط الكبرى، واجعل الأبناء يستهلكون السياق دون الحاجة لتكرار البيانات أو طلبها يدوياً”.

الصورة الرمزية لـ Mohamed Abozaid

م. محمد أبو زيد

WordPress Architect & Enterprise Consultant

مهندس برمجيات متخصص في تطوير حلول ووردبريس المتقدمة، معمارية Block Themes، ومحرر Gutenberg، وتحسين الأداء لمواقع الشركات الكبرى في مصر والخليج العربي.


اترك تعليقاً