الوسم embed في Twig

من موسوعة حسوب

يجمع وسم embed سلوك كل من الوسمين include و extends، إذ يسمح لك بإدراج محتويات قالب آخر كما يفعل include، كذلك يسمح لك بتخطي أي كتلة معرفة داخل القالب المدرَج كما يحدث عند توسيع قالب ما، ويمكن النظر إلى القالب المضمَّن على أنه هيكل واجهة مصغر (micro layout skeleton).

{% embed "teasers_skeleton.twig" %}
    {# "teasers_skeleton.twig" هذه الكتل معرفة في #}
    {# ونحن نتخطاها من هنا:                    #}
    {% block left_teaser %}
        بعض المحتوى للصندوق الأيسر
    {% endblock %}
    {% block right_teaser %}
        بعض المحتوى للصندوق الأيسر
    {% endblock %}
{% endembed %}

ينقل الوسم embed مبدأ وراثة القالب ليجعله على مستوى أجزاء المحتوى، فإن كانت وراثة القالب تسمح لك بإنشاء ما يشبه هياكل المستندات التي تُملأ بقوالب فرعية، فإن وسم embed يسمح لك بإنشاء هياكل لوحدات صغيرة من المحتوى، وتعيد استخدامها في أي مكان تريد. انظر المثال المبسط التالي الذي يوضح حالة استخدام لوسم embed، والذي يُشارَك فيه قالب أساسي بواسطة عدة صفحات HTML، ويعرّف كتلة وحيدة اسمها "content":

┌─── تخطيط الصفحة ───────────────────────┐
│                                     │
│           ┌── "content" كتلة  ────┐   │
│           │                     │   │
│           │                     │   │
│           │ (ضع قالبًا فرعيًا هنا)      │   │
│           │                     │   │
│           │                     │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

تتشارك بعض الصفحات -لتكن "foo" و "bar"- نفس بنية المحتوى، وهي صندوقين رأسيين فوق بعضهما:

┌─── تخطيط الصفحة ───────────────────────┐
│                                     │
│           ┌── "content" الكتلة ────┐   │
│           │ ┌─ "top" الكتلة ─────┐ │   │
│           │ │                 │ │   │
│           │ └─────────────────┘ │   │
│           │ ┌ "bottom" الكتلة ───┐ │   │
│           │ │                 │ │   │
│           │ └─────────────────┘ │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

وتتشارك صفحات أخرى -مثل "boom" و "baz"- بنية مختلفة للمحتوى، على هيئة صندوقين متجاورين:

┌─── تخطيط الصفحة ───────────────────────┐
│                                     │
│           ┌── "content" الكتلة ────┐   │
│           │                     │   │    
│           │ ┌─ كتلة ┌ ┐── كتلة ───┐ │   │
│           │ │"left" │ │"right"│ │   │
│           │ │       │ │       │ │   │
│           │ │       │ │       │ │   │
│           │ └───────┘ └───────┘ │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

سيكون لديك طريقتان تصمم بهما قوالبك من غير استخدام وسم embed:

  • إنشاء قالبين أساسيين وسيطين (intermediate) يوسعان تخطيط القالب الأصلي، واحد بصناديق رأسية لتستخدمه صفحتي foo و bar، والآخر بصناديق جنبًا إلى جنب لتستخدمه صفحتي boom و baz.
  • تضمين ترميز الصناديق في قالب كل صفحة مباشرة.

غير أن هاتين الطريقتين فيهما أوجه قصور كبيرة:

  • فالطريقة الأولى وإن كانت ستنجح في هذا المثال البسيط، إلا أننا لو أضفنا شريطًا جانبيًا سيحتوي على هياكل أخرى مختلفة ومتكررة للمحتوى، فسنحتاج إلى إنشاء قوالب أساسية وسيطة لكل تجميعات هياكل المحتوى تلك، ولهيكل الشريط الجانبي، وهكذا.
  • أما الطريقة الثانية فيدخل فيها تكرار لشيفرة مشتركة، وعيب ذلك أن أي تغيير سيعني إيجاد جميع نسخ الهيكل الذي تم عليه التغيير وتعديلها جميعًا، ويجب أن يحقَّق التصحيح في كل نسخة، وربما تخرج النسخ عن المزامنة بسبب تعديلات غير منضبطة، وهكذا.

وهنا في مثل تلك الحالة تبرز أهمية وسم embed، إذ يمكن أن تظل شيفرة التخطيط المشتركة في قالب أساسي واحد، ثم تذهب هياكل المحتوى المختلفة التي يمكن أن نسميها هنا "تخطيطات مصغرة" إلى قوالب منفصلة تضمَّن عند الحاجة:

قالب الصفحة foo.twig:

{% extends "layout_skeleton.twig" %}

{% block content %}
    {% embed "vertical_boxes_skeleton.twig" %}
        {% block top %}
            بعض المحتوى للصندوق العلوي
        {% endblock %}

        {% block bottom %}
            بعض المحتوى للصندوق السفلي
        {% endblock %}
    {% endembed %}
{% endblock %}

وفيما يلي شيفرة vertical_boxes_skeleton.twig:

<div class="top_box">
    {% block top %}
        المحتوى الافتراضي للصندوق العلوي
    {% endblock %}
</div>

<div class="bottom_box">
    {% block bottom %}
        المحتوى الافتراضي للصندوق السفلي
    {% endblock %}
</div>

والهدف من قالب vertical_boxes_skeleton.twig هو استبعاد ترميز HTML من الصناديق. يأخذ الوسم embed نفس الوسائط التي يأخذها الوسم include:

{% embed "base" with {'foo': 'bar'} %}
    ...
{% endembed %}

{% embed "base" with {'foo': 'bar'} only %}
    ...
{% endembed %}

{% embed "base" ignore missing %}
    ...
{% endembed %}

انتبه إلى أن خطط التهريب التلقائي التي تبنى على أسماء القوالب لن تعمل كما تتوقع لها إذا غيرت السياق، بأن تضمِّن قالب CSS أو جافاسكربت مثلًا في قالب HTML، وذلك لأن القوالب المضمنة ليس لها أسماء. وفي مثل تلك الحالة، اضبط الخطة الافتراضية للتهريب التلقائي باستخدام وسم autoescape.

انظر أيضًا

المصادر