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

خصائص بلوكات Gutenberg: هندسة الـ Attributes، مصادر استخراج القيم، وحماية التوافقية

رسم مفاهيمي يوضح خصائص بلوكات Gutenberg ضمن سلسلة تطوير ووردبريس
📋 فهرس محتويات المقال (اضغط للتنقل السريع) ▾

يا أهلاً بيك يا هندسة في واحد من أدق وأهم أسرار النضج البرمجي في محرر ووردبريس الحديث: خصائص البلوكات (Block Attributes) وهندسة مصادر استخراج القيم. لما تبدأ تطور بلوك في جوتنبرج، أول حاجة بتفكر فيها هي: “أنا هخزن بيانات البلوك دي فين؟” هل هرمي كل المتغيرات كـ JSON جوة تعليق البلوك <!-- wp:my/block {"title":"..."} -->؟ ولا استخرجها بذكاء من كود الـ HTML الدلالي نفسه؟ ولا أربطها بجدول الـ Postmeta عشان استعلم عنها بـ WP_Query؟ الاختيار اللي هتاخده هنا هو اللي هيحدد هل موقعك هيكون فائق الرشاقة وخفيف زي الريشة، أو هتتسبب في تضخم قاعدة البيانات بجيجابايتات من البيانات المكررة وعشرات أخطاء الـ Block Invalidation عند كل تحديث! في الدليل الشامل ده، هنفكك معمارية الـ Attributes بالكامل، ونفهم محرك الـ DOM Matcher في جوتنبرج، ونبني بلوكات مؤسسية مطابقة لأعلى المعايير العالمية.

ما هي خصائص البلوك (Attributes) ولماذا هي عصب المعمارية؟

في هندسة ووردبريس المعاصرة، البلوك مش مجرد رسمة أو وسم HTML ثابت؛ البلوك هو عبارة عن مكون برمجي ذو حالة (Stateful Component). الـ Attributes هي الحاوية اللي بتحتفظ بحالة هذا المكون: نصوص العناوين، مسار الصورة (Image URL)، ألوان الخلفية، عدد الأعمدة، حالة التفعيل (Toggle State)، وخيارات المحاذاة.

الـ Attributes بتلعب دور “حلقة الوصل” بين 3 عوالم مختلفة:

  1. عالم التحرير في React (edit.js): حيث يتم قراءة الخصائص كـ Props وتعديلها عبر setAttributes() في الذاكرة.
  2. عالم التخزين في الداتابيز (MySQL Database): حيث يتم حفظها إما كـ JSON Delimiters أو داخل وسوم HTML أو كـ Post Meta.
  3. عالم العرض في الفرونت إند (save.js أو render.php): حيث تتحول الخصائص إلى عناصر واجهة يراها الزائر.

استراتيجيات التخزين ومصادر الاستخراج (Attribute Sources)

ووردبريس بيوفر 3 استراتيجيات معمارية لتخزين واسترجاع الـ Attributes:

1. التخزين الافتراضي في تعليقات الـ HTML (Comment Delimiters)

لو عرفت الخاصية في block.json بنوعها وقيمتها الافتراضية فقط بدون تحديد source:

"attributes": {
  "columnsCount": {
    "type": "number",
    "default": 3
  }
}

ووردبريس هيقوم بتخزين القيمة دي كـ JSON صريح داخل تعليق البلوك في قاعدة البيانات: <!-- wp:my/block {"columnsCount":4} -->. الميزة: سهلة ومباشرة وسريعة جداً ومثالية للبيانات الوصفية (Metadata) اللي ملهاش تمثيل بصري في كود الـ HTML (زي عدد الأعمدة، أو حالة تفعيل خيار معين). العيب: لو استخدمتها للنصوص والصور، هتخزن البيانات مرتين (مرة في الـ JSON ومرة في الـ HTML)، مما يضاعف حجم قاعدة البيانات بلا داعٍ.

2. الاستخراج الذكي من شجرة الـ DOM (DOM Source Attributes)

ودي بقى قمة العبقرية الهندسية في جوتنبرج! بدل ما تخزن نص المقال أو رابط الصورة في الـ JSON، أنت بتقول لووردبريس: “أنا هطبع القيمة دي في كود الـ HTML في دالة save.js، ولما المحرر يفتح المقال تاني، استخرج القيمة دي من شجرة الـ DOM مباشرة!” جوتنبرج بيدعم 4 محددات استخراج رئيسية:

  • المصدر text: يستخرج النص المجرد من العنصر بدون وسوم:
    "title": {
      "type": "string",
      "source": "text",
      "selector": "h2.az-block-title"
    }
  • المصدر html: يستخرج كود الـ HTML الداخلي بما يحتويه من وسوم غنية (Bold, Italic, Links):
    "description": {
      "type": "string",
      "source": "html",
      "selector": "div.az-description-body"
    }
  • المصدر attribute: يستخرج قيمة سمة محددة من وسم HTML معين (مثل src أو href أو alt أو data-id):
    "imageUrl": {
      "type": "string",
      "source": "attribute",
      "selector": "img.az-feature-img",
      "attribute": "src"
    }
  • المصدر query: يستخرج مصفوفة كائنات متكررة من عناصر الـ DOM (مثالي لقوائم الروابط، عناصر المعارض، أو جداول المقارنة):
    "galleryImages": {
      "type": "array",
      "source": "query",
      "selector": "figure.gallery-item",
      "query": {
        "url": { "type": "string", "source": "attribute", "selector": "img", "attribute": "src" },
        "caption": { "type": "string", "source": "text", "selector": "figcaption" }
      }
    }

3. الربط المباشر مع الحقول المخصصة (Post Meta Attributes)

لو عندك بيانات حساسة أو محتاج تستعلم عنها في فلترات وبحث ووردبريس بـ meta_query (زي سعر المنتج، كود العقار، أو تاريخ انتهاء الدورة التدريبية)، التخزين جوة محتوى المقال مش هيفيدك في الاستعلامات السريعة. هنا بنستخدم "source": "meta":

"attributes": {
  "propertyPrice": {
    "type": "number",
    "source": "meta",
    "meta": "_real_estate_price"
  }
}

بمجرد ما المحرر يغير السعر في البلوك، ووردبريس بيحفظه تلقائياً في جدول wp_postmeta عبر الـ REST API، ويصبح متاحاً للاستعلامات البرمجية فائقة السرعة!

مقارنة معمارية شاملة: استراتيجيات تخزين واستخراج الخصائص

المعيار الهندسيالاستخراج من شجرة الـ DOM (Source: html/text/attribute)التخزين في تعليقات البلوك (Comment JSON)الربط بجدول Post Meta (Source: meta)
توفير حجم قاعدة البيانات (Storage Overhead)مثالي؛ صفر ازدواجية، تخزين القيمة مرة واحدة فقط في الـ HTMLمضاعف؛ يتم تخزين نفس النص مرتين (في JSON وفي الـ HTML)منفصل؛ يتم التخزين كسطر مستقل في جدول wp_postmeta
سرعة الفك والتحليل في الذاكرة (Parsing Speed)تتطلب تشغيل محرك DOM Parser لاستخراج الحقولفائقة السرعة عبر فك كود الـ JSON المباشرسريعة جداً وتعتمد على كاش الميتا المدمج بالنواة
التوافق مع استعلامات WP_Queryمنعدم؛ لا يمكن الاستعلام عنه إلا ببحث نصي بطيءمنعدم؛ الـ JSON مخزن كنص خام مشفر داخل المحتوىمثالي؛ يدعم الفلترة، الترتيب، والبحث المتقدم بالـ meta_query
التوافق مع معمارية Headless APIsيتطلب تحليل شجرة الـ AST للحصول على الحقولسهل ومتاح مباشرة كـ Attributes في كائن الـ JSON المرجعمباشر عبر حقل meta في الـ REST API الرسمي
مقاومة أخطاء الـ Block Invalidationحساسة؛ تتطلب تطابق الـ Selectors مع الـ HTML المحفوظمحصنة ضد تغيرات هيكل الـ DOM في الواجهةمحصنة تماماً ومستقلة عن بنية المحتوى

تطبيق برودكشن متكامل: بناء بلوك شهادات عملاء مؤسسي يدمج كافة مصادر الخصائص

تعال نبني كود برودكشن حقيقي لبلوك شهادات العملاء (Enterprise Testimonial Block). البلوك ده بيوظف كل أنواع الـ Attributes بحرفية: استخراج النصوص بـ html و text، استخراج رابط الصورة بـ attribute، وتخزين التقييم النجمي كـ Comment JSON:

1. ملف البيانات الوصفية (block.json)

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "enterprise/client-testimonial",
  "version": "1.0.0",
  "title": "شهادة عميل مؤسسية",
  "category": "widgets",
  "icon": "format-quote",
  "description": "بلوك لعرض آراء وتقييمات العملاء مع استخراج ذكي من شجرة الـ DOM لتوفير الذاكرة.",
  "supports": {
    "color": {
      "background": true,
      "text": true
    },
    "spacing": {
      "padding": true
    }
  },
  "attributes": {
    "clientName": {
      "type": "string",
      "source": "text",
      "selector": "h4.client-name",
      "default": "م. أحمد عبد الرحمن"
    },
    "clientCompany": {
      "type": "string",
      "source": "text",
      "selector": "span.client-company",
      "default": "شركة القاهرة للحلول الرقمية"
    },
    "testimonialText": {
      "type": "string",
      "source": "html",
      "selector": "blockquote.testimonial-quote",
      "default": "التعامل مع المنصة نقل أعمالنا لمستوى آخر من الاحترافية والسرعة الاستثنائية."
    },
    "avatarUrl": {
      "type": "string",
      "source": "attribute",
      "selector": "img.client-avatar",
      "attribute": "src",
      "default": "https://via.placeholder.com/150"
    },
    "avatarAlt": {
      "type": "string",
      "source": "attribute",
      "selector": "img.client-avatar",
      "attribute": "alt",
      "default": "صورة العميل"
    },
    "ratingStars": {
      "type": "number",
      "default": 5
    }
  },
  "editorScript": "file:./index.js",
  "style": "file:./style-index.css"
}

2. مكون التحرير التفاعلي (edit.js)

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

export default function Edit({ attributes, setAttributes }) {
    const { 
        clientName, 
        clientCompany, 
        testimonialText, 
        avatarUrl, 
        avatarAlt, 
        ratingStars 
    } = attributes;

    const blockProps = useBlockProps({
        className: 'az-enterprise-testimonial-block'
    });

    return (
        
            
                
                     setAttributes({ ratingStars: val })}
                        min={1}
                        max={5}
                    />
                
            

            
setAttributes({ avatarUrl: media.url, avatarAlt: media.alt || clientName })} allowedTypes={['image']} render={({ open }) => ( )} />
setAttributes({ clientName: val })} placeholder={__('اسم العميل...', 'text-domain')} /> setAttributes({ clientCompany: val })} placeholder={__('الشركة أو المنصب...', 'text-domain')} />
{'★'.repeat(ratingStars)}{'☆'.repeat(5 - ratingStars)}
setAttributes({ testimonialText: val })} placeholder={__('اكتب نص الشهادة أو التوصية هنا...', 'text-domain')} />

3. دالة الحفظ والتصيير (save.js)

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

export default function save({ attributes }) {
    const { 
        clientName, 
        clientCompany, 
        testimonialText, 
        avatarUrl, 
        avatarAlt, 
        ratingStars 
    } = attributes;

    const blockProps = useBlockProps.save({
        className: 'az-enterprise-testimonial-block'
    });

    return (
        
{avatarAlt}
{'★'.repeat(ratingStars)}{'☆'.repeat(5 - ratingStars)}
); }

تفكيك الكود وشرح فلسفته التخزينية بالعامية المصرية

تعال نبص على السحر المعماري اللي بيحصل في قاعدة البيانات لما بنحفظ البلوك ده:

  • ما يتم تخزينه في تعليق البلوك: لما تفتح جدول wp_posts، هتلاقي التعليق مكتوب كده بالظبط: <!-- wp:enterprise/client-testimonial {"ratingStars":5} -->! لاحظت حاجة مبهرة؟ اسم العميل، شركته، نص الشهادة الطويل، ورابط الصورة مش موجودين في الـ JSON نهائياً! الخاصية الوحيدة اللي اتخزنت في الـ JSON هي ratingStars لأنها ملهاش وسم مباشر نستخرجها منه.
  • توفير الذاكرة وسرعة الـ Parsing: وفرنا مئات البايتات من النصوص المتكررة في كل بلوك. لما المحرر يفتح المقال، ووردبريس بيشغل الـ DOM Matcher ويروح يقرأ h4.client-name ويملا بيه attributes.clientName فوراً، بدون ما يستهلك رامات السيرفر وبدون ما يكرر النصوص في الداتابيز.
  • التعامل الآمن مع الصور عبر الوسم الدلالي: ربطنا avatarUrl بـ src و avatarAlt بـ alt في وسم <img class="client-avatar">. ده بيضمن إن الصورة تكون متوافقة بنسبة 100% مع معايير الـ SEO والـ Accessibility، وفي نفس الوقت مستخرجة بدقة متناهية.

دراسة حالة واقعية من السوق المصري: إنقاذ منصة مصانع أثاث دمياط من تضخم الـ 18 جيجابايت

تعال أحكيلك كواليس واقعة هندسية حقيقية لواحد من أكبر المتاجر الإلكترونية المتخصصة في تسويق أثاث دمياط في مصر (القاهرة ودمياط والخليج):

الكارثة المعمارية وتضخم البيانات

المنصة كان عليها أكثر من 35,000 منتج وتشكيلة أثاث، وكل منتج معروض بصفحة هبوط مبنية ببلوكات مخصصة طورها فريق سابق. المطورين القدامى مكنوش فاهمين معمارية الـ Attribute Sources؛ فعرفوا كل مواصفات الأثاث (نوع الخشب، المقاسات، الألوان، خامات الأقمشة، الضمان، وفيديو المعاينة) كـ Comment JSON عادي بدون أي source! النتيجة في قاعدة البيانات: 1. كل مقال كان جواه تعليق بلوك ضخم فيه JSON حجمه يتجاوز 15 كيلوبايت، مكرر جواه نفس النصوص اللي مكتوبة في كود الـ HTML! 2. جدول wp_posts قفز حجمه لـ 18.4 جيجابايت! 3. استعلامات البحث وتصدير البيانات بقت تاخد دقائق، والسيرفر كان بيرمي أخطاء Out of Memory أثناء النسخ الاحتياطي اليومي (Daily Backups)!

خطة الإنقاذ بالتحول إلى DOM Sources

  1. إعادة هندسة الـ Attributes وتحديد محددات الـ DOM: قمنا بتعديل ملف block.json، وربطنا كل نص بـ source: "text" أو "html" مع الـ CSS Selectors المناسبة، وحولنا الأسعار والمقاسات للميتا بـ source: "meta" لتمكين الفلترة السريعة.
  2. تشغيل سكريبت تنظيف لقاعدة البيانات (Normalization Script): كتبنا سكريبت PHP مر على الـ 35,000 مقال، وفكك تعليقات البلوكات القديمة، وحذف كتل الـ JSON المكررة والزائدة عن الحاجة مع الإبقاء على كود الـ HTML النظيف فقط.
  3. تفعيل محددات الفهرسة: قمنا بفهرسة حقول الميتا في جدول wp_postmeta لتسريع استعلامات تصفية غرف النوم والصالونات بحسب نوع الخشب والسعر.

جدول نتائج التحول الهندسي

المؤشر الفني والتشغيليقبل التحول (Naive Comment JSON)بعد التحول (Smart DOM Sources)نسبة الوفر والتحسن
حجم جدول wp_posts في قاعدة البيانات18.4 GB (تضخم كارثي)2.2 GB فقط!تخفيض حجم الداتابيز بنسبة 88%
متوسط زمن أخذ النسخة الاحتياطية (Backup)45 دقيقة (مع حالات فشل متكررة)3 دقائق فقط بسلاسة تامةتسريع النسخ بمقدار 15 ضعفاً
زمن استعلامات تصفية المنتجات في المتجر3,400 ms65 ms بفضل الـ Meta Indexingتسريع الاستعلامات بـ 52 ضعفاً
استقرار محرر جوتنبرج عند فتح المنتجاتتجميد المتصفح بسبب كبر حجم الـ JSONفتح فوري واستهلاك ضئيل للراماتاستقرار بيئة التحرير بنسبة 100%

الوصايا العشر لتصميم خصائص بلوكات Gutenberg

  1. استخدم DOM Sources للنصوص والصور دائماً: لا تخزن نصوص العناوين أو روابط الصور في تعليقات الـ JSON لتفادي ازدواجية البيانات وتضخم الداتابيز.
  2. اقتصر في Comment JSON على البيانات الوصفية (Metadata): استخدمه فقط للأرقام المجردة، والخيارات المنطقية (Booleans)، والإعدادات التي ليس لها تمثيل في الـ HTML.
  3. حدد نوع الخاصية بدقة (Strict Typing): حدد دائماً هل الخاصية string، number، boolean، أو array لتفادي مشاكل الـ Serialization.
  4. ضع قيماً افتراضية (Default Values) منطقية: احرص على تزويد كل خاصية بقيمة افتراضية لمنع ظهور أخطاء undefined في واجهة React.
  5. استخدم source: "meta" للبيانات القابلة للبحث: أي قيمة تحتاج لفلترتها أو الاستعلام عنها عبر WP_Query يجب ربطها بالميتا داتا.
  6. احرص على تطابق الـ Selectors مع كود save.js: إذا تغير اسم الكلاس في كود دالة الحفظ، يجب تحديث الـ Selector في block.json ومصفوفة الـ Deprecation.
  7. لا تخزن كائنات برمجية معقدة في الـ Attributes: بسط هياكل بياناتك؛ استخدام مصفوفات بسيطة وأرقام يسهل قراءتها وصيانتها.
  8. طهر البيانات قبل تعيينها بـ setAttributes: تأكد من تحويل المدخلات العددية بـ parseFloat أو parseInt قبل تمريرها للحالة.
  9. احذر من تغيير نوع الخاصية دون ترقية (Migration): تغيير نوع الخاصية من string إلى array يتطلب حتماً توثيق النسخة السابقة في deprecated.
  10. اختبر استخراج الخصائص عند إعادة فتح المحرر: تأكد بعد حفظ المقال وإغلاق المتصفح وإعادة فتحه أن كافة الخصائص تم استخراجها بنجاح دون أي فقد للبيانات.

التعمق المعماري: خوارزمية تطبيع الخصائص والتحويل التلقائي (Type Coercion)

يا صديقي المطور، من أدق أسرار محرك جوتنبرج في JavaScript (حزمة @wordpress/blocks) هي الطريقة اللي بيتعامل بيها مع الـ Type Coercion لما يستخرج القيم من شجرة الـ DOM. في لغة HTML، أي سمة (Attribute) داخل وسم، زي data-count="42" أو data-price="199.99"، بتخرج افتراضياً من المتصفح كنص صريح (String). لو محرك جوتنبرج أخد النص ده وحطه في attributes.count بدون ذكاء، وأنت معرف الخاصية في block.json كـ type: "number"، المقارنة في React هتضرب وهتلاقي "42" === 42 بترجع false! هنا بيتدخل محرك Attribute Normalizer: بيقوم بقراءة نوع الخاصية المحدد في block.json، وبيمرر القيمة النصية المستخرجة من الـ DOM على دوال تحويل صارمة: إذا كان النوع number بيشغل Number(value)، وإذا كان boolean بيتحقق من وجود السمة أو مطابقتها لـ "true"، وإذا كان array بيقسم العناصر إذا كانت مفصولة بفواصل أو يستخرجها عبر source: "query". ده بيضمن إن مكون React بتاعك في edit.js يستلم دائماً أنواع بيانات نقية ومطابقة للعقد البرمجي (Strict Types).

ربط الخصائص بكيانات النواة عبر @wordpress/core-data

في البلوكات المتقدمة، ساعات بنحتاج البلوك يعرض بيانات مش متخزنة جواه أصلاً؛ زي جلب اسم الكاتب، أو صورة المقال البارزة (Featured Image)، أو أحدث التعليقات. بدل ما تخزن البيانات دي في الـ Attributes وتضطر تحدثها يدوياً لو الكاتب غير اسمه، جوتنبرج بيوفر خطافات Entity Data Hooks:

import { useEntityProp } from '@wordpress/core-data';

export default function Edit({ context: { postId, postType } }) {
    // قراءة وتعديل عنوان المقال الأصلي مباشرة من داخل البلوك!
    const [ title, setTitle ] = useEntityProp('postType', postType, 'title', postId);

    return (
         setTitle(e.target.value)} 
            className="direct-post-title-editor"
        />
    );
}

في النمط المعماري ده، البلوك مبيخزنش title في الـ Attributes بتاعته خالص؛ البلوك شغال كـ Interface مباشر لكيان المقال في Redux Store، وده اللي بيحقق التكامل التام في بيئة Full Site Editing (FSE).

التعمق المعماري: ترطيب القيم الافتراضية (Attributes Hydration) في بيئات Headless

يا صديقي المطور، في تطبيقات الـ Headless المبنية بـ Next.js و React، المطورين ساعات بيشتكوا من لغز غريب: "لما بطلب المقال عبر الـ REST API وبفكك البلوكات بـ parse_blocks()، كائن attrs بيكون فاضي ومفهوش الخصائص اللي معرفينها بقيم افتراضية في block.json!" السبب المعماري في ده: ووردبريس عشان يوفر مساحة قاعدة البيانات، مبيخزنش الخصائص اللي قيمتها مطابقة للـ default value! هو بيخزن فقط الخصائص اللي المحرر غير قيمتها يدوياً. عشان كائن البلوك يرجع مكتمل بالقيم الافتراضية في الـ REST API لتطبيقات الموبايل والفرونت إند، لازم نطبق عملية Attributes Hydration نواتية: نستدعي الكلاس WP_Block_Type_Registry::get_instance()->get_registered($block_name)، وندمج مصفوفة $block_type->attributes مع الـ $parsed_block['attrs'] عبر wp_parse_args(). الخطوة الهندسية دي بتضمن إن تطبيق Next.js أو Flutter يستلم كائن JSON متكامل وثابت وخالي من أخطاء الـ Undefined Properties، وده اللي بيبني أنظمة برمجية صلبة لا تهتز أمام أي تغيرات بيئية.

الأسئلة الشائعة حول خصائص بلوكات Gutenberg (20 سؤالاً تقنياً)

1. ما هو الفرق الجوهري بين Comment Attribute و DOM Source Attribute؟

الـ Comment Attribute يخزن القيمة كـ JSON صريح داخل تعليق البلوك في الداتابيز. أما DOM Source Attribute فيستخرج القيمة ديناميكياً من داخل وسوم كود الـ HTML المحفوظ باستخدام محددات CSS (Selectors) دون تكرار تخزينها.

2. متى يجب عليّ استخدام source: "html" بدلاً من source: "text"؟

نستخدم source: "html" عندما يحتوي النص على تنسيقات غنية (مثل وسوم <strong>، <em>، وروابط <a>). أما source: "text" فيستخدم عندما نريد استخراج النص الصافي مجرداً من أي وسوم داخلية.

3. كيف استخرج رابط صورة من وسم <img> في كود البلوك؟

باستخدام: "source": "attribute" مع تحديد "selector": "img" وتحديد السمة المستهدفة "attribute": "src" في مواصفات الخاصية بملف block.json.

4. ما هي وظيفة المصدر source: "query"؟

يستخدم لاستخراج مصفوفة من العناصر المتكررة من شجرة الـ DOM (مثل استخراج قائمة عناصر كل عنصر منها يحتوي على عنوان ورابط وصورة) وتحويلها إلى مصفوفة كائنات في React.

5. كيف أربط خاصية في البلوك بحقل مخصص في جدول الـ Post Meta؟

بتحديد "source": "meta" وتمرير اسم مفتاح الميتا في خاصية "meta": "my_custom_key"، مع ضرورة تسجيل الحقل في PHP عبر register_post_meta() مع تفعيل 'show_in_rest' => true.

6. لماذا تختفي بعض الخصائص عند تحديث الصفحة رغم حفظها؟

يحدث ذلك عادة عندما يتم تحديد source ولكن محدد الـ selector غير متطابق حرفياً مع كود الـ HTML المولد من دالة save.js، فيفشل محرك جوتنبرج في العثور على القيمة أثناء التحليل.

7. ماذا يحدث إذا لم أحدد خاصية source في تعريف الـ Attribute؟

يقوم ووردبريس تلقائياً بتخزين الخاصية وقيمتها كـ JSON داخل تعليق البلوك الافتراضي <!-- wp:block {"attr":"val"} -->.

8. هل يمكن استخدام setAttributes() لتعديل أكثر من خاصية في نفس اللحظة؟

نعم، تقبل دالة setAttributes() كائناً يحتوي على عدة خصائص (مثل setAttributes({ title: 'جديد', price: 100 })) وتقوم بتحديث الحالة دفعة واحدة.

9. كيف أتعامل مع الخصائص ذات القيم المنطقية (Boolean Attributes)؟

تحدد بنوع "type": "boolean" مع قيمة افتراضية true أو false، وتخزن افتراضياً كـ Comment Attributes لعدم وجود تمثيل دلالي مباشر لها في الـ DOM.

10. كيف أمنع تضخم قاعدة البيانات عند استخدام بلوكات تحتوي على نصوص طويلة؟

بالاعتماد الكامل على source: "html" أو source: "text"؛ حيث يتم حفظ النص مرة واحدة فقط في الـ HTML ويتكفل المحرك باستخراجه عند الحاجة دون تكراره في تعليقات الـ JSON.

11. هل يؤثر طول مصفوفة الـ Attributes على سرعة محرر جوتنبرج؟

بشكل طفيف أثناء الـ DOM Extraction، ولكن عند اتباع أفضل الممارسات واستخدام محددات CSS دقيقة ومباشرة، فإن عملية الاستخراج تستغرق أجزاء ضئيلة من الميكروثانية.

12. كيف أختبر صحة استخراج الخصائص برمجياً في المتصفح؟

بفتح الـ Console وكتابة: wp.data.select('core/block-editor').getSelectedBlock().attributes لمعاينة كائن الخصائص المستخرج للبلوك المحدد حالياً.

13. ما هو دور خاصية selector عند استخدام source: "attribute"؟

تحدد العنصر المستهدف بدقة داخل كود البلوك (مثل a.btn-link) الذي سيتم استخراج قيمة السمة (مثل href) منه.

14. هل يمكن استخدام تعبير نمطي (Regex) لتصفية القيمة المستخرجة من الـ DOM؟

لا يدعم ووردبريس الـ Regex المباشر داخل تعريف block.json، ولكن يمكن تنظيف القيمة المستخرجة داخل كود الـ JavaScript في مكون edit.js أو في معالجات الـ Migration.

15. كيف أتعامل مع الصور ذات الأحجام المتعددة في الـ Attributes؟

بتخزين المعرف الرقمي للصورة imageId كـ Comment Attribute، واستخراج رابط العرض الافتراضي من وسم الـ img عبر source: "attribute".

16. ماذا يحدث للـ Attributes غير المعرفة في block.json إذا وصلت في تعليق البلوك؟

يتجاهلها محرك جوتنبرج افتراضياً ولا يمررها لكائن attributes في مكون التحرير، ما لم تكن هناك معالجات ترقية مخصصة.

17. هل تدعم الـ Attributes قيم التاريخ والوقت؟

نعم، تخزن عادة كـ string بتنسيق ISO 8601 القياسي (مثل 2026-11-01T14:00:00Z) مع تحويلها لكائنات Date في JavaScript عند الحاجة.

18. كيف أضمن عدم حدوث أخطاء إذا كانت القيمة المستخرجة من الـ DOM فارغة؟

بتحديد خاصية "default" دائماً في تعريف الحقل بملف block.json لتكون صمام الأمان الذي يرجع إليه المحرك عند غياب القيمة.

19. ما هو الفرق بين multiline: "p" في RichText وعلاقتها بـ source: "html"؟

الخاصية multiline: "p" تجعل RichText يولد فقرات <p> متعددة عند ضغط Enter، مما يتطلب حتماً استخدام source: "html" لاستخراج بنية الفقرات بالكامل دون تشويه.

20. ما هي القاعدة الذهبية لاختيار مصدر الـ Attribute المناسب؟

"إذا كان الشيء يظهر في الواجهة استخرجه من الـ DOM، وإذا كان خياراً تحكمياً اخزنه في تعليق الـ JSON، وإذا كان بياناً للبحث والفلترة احفظه في الـ Post Meta".

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

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

WordPress Architect & Enterprise Consultant

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


اترك تعليقاً