الوسم extends في Twig

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

يُستخدم الوسم extends مع قالب ليرث من قالب آخر.

لاحظ أن Twig لا يدعم الوراثة المتعددة شأنه في ذلك شأن لغة PHP، فلا يمكنك استدعاء إلا وسم extends واحد عند كل إخراج rendering، لكن Twig يدعم إعادة الاستخدام الأفقية horizontal reuse، انظر وسم use.

لنعرّف قالبًا أساسيًا base template هو base.html، الذي يعرّف مستند HTML هيكلي:

<!DOCTYPE html>
<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css"/>
            <title>{% block title %}{% endblock %} - My Webpage</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>

تعرّف أوسمة block في المثال السابق أربعة كتل تستطيع القوالب الأبناء أن تملأها، ويخبر وسم block محرك القالب أن القالب الابن قد يتخطى هذه الأجزاء من القالب.

القالب الابن

الشيفرة التالية مثال على قالب ابن child template:

{% extends "base.html" %}

{% block title %}Index{% endblock %}
{% block head %}
    {{ parent() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Index</h1>
    <p class="important">
        Welcome on my awesome homepage.
    </p>
{% endblock %}

في المثال أعلاه يخبر الوسم extends محرك القالب أن هذا القالب يوسع قالبًا آخر، وعندما يقيّم نظام القالب هذا القالب فإنه يحدد قالبه الأب أولًا، ويجب أن يكون الوسم extends هو أول وسم في القالب.

وبما أن القالب الابن لا يعرّف كتلة footer فإن القيمة التي من القالب الأب هي التي تُستخدم. لا تستطيع تعريف عدة وسوم block بنفس الاسم في نفس القالب، وهذا لأن وسم block يعمل في اتجاهين، فإنه يوفر فراغًا لملئه ويعرّف المحتوى الذي يملأ ذلك الفراغ في القالب الأب في نفس الوقت، وإذا كان لدينا وسمان block في قالب واحد فإن القالب الأب لن يعرف أي الوسمين يختار كي يستخدم محتواه.

لكن إذا أردت طباعة كتلة عدة مرات فيمكنك استخدام دالة block:

<title>{% block title %}{% endblock %}</title>
<h1>{{ block('title') }}</h1>
{% block body %}{% endblock %}

الكتلة الأب

من الممكن إخراج محتويات الكتلة الأب باستخدام دالة parent، ويعطينا ذلك نتيجة الكتلة الأب:

{% block sidebar %}
    <h3>Table Of Contents</h3>
    ...
    {{ parent() }}
{% endblock %}

وسم النهاية للكتلة المسماة

يسمح لك Twig أن تضع اسم الكتلة بعد وسم النهاية من أجل تيسير قراءتها، ويجب أن يطابق الاسم الذي بعد كلمة endblock اسم الكتلة:

{% block sidebar %}
    {% block inner_sidebar %}
        ...
    {% endblock inner_sidebar %}
{% endblock sidebar %}

نطاق الكتل وتشعبها

من الممكن أن تتشعب الكتل لتنشئ بها تخطيطات معقدة، وإن لها افتراضيًا وصول إلى المتغيرات من النطاقات الخارجية:

{% for item in seq %}
    <li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}

اختصارات الكتل

من الممكن استخدام صياغة مختصرة في حالة الكتل التي ليس بها محتوى كبير، والبنى التالية تنفذ مثل ذلك:

{% block title %}
    {{ page_title|title }}
{% endblock %}
{% block title page_title|title %}

الوراثة الديناميكة

يدعم Twig الوراثة الديناميكية Dynamic Inheritance عن طريق استخدام المتغير كقالب أساسي base template:

{% extends some_var %}

إذا كان المتغير يقيَّم إلى ‎\Twig\Template أو نسخة من ‎\Twig\TemplateWrapper فإن Twig سيستخدمه كقالب أب:

// {% extends layout %}

$layout = $twig->load('some_layout_template.twig');

$twig->display('template.twig', ['layout' => $layout]);

يمكنك توفير قائمة من القوالب التي تم التحقق من وجودها، وسيُستخدم أول قالب موجود كقالب أب:

{% extends ['layout.html', 'base_layout.html'] %}

الوراثة الشرطية

بما أن اسم القالب الأب قد يكون أي تعبير Twig صالح، فمن الممكن أن نجعل آلية الوراثة آلية شرطية:

{% extends standalone ? "minimum.html" : "base.html" %}

في المثال أعلاه، يوسِّع القالب قالب التخطيط "minimum.html" إذا قُيِّم المتغير standalone إلى true، ويوسع "base.html" إن كان false.

كيفية عمل الكتل

توفر الكتلة طريقة لتغيير الكيفية التي يُخرَج بها جزء ما من القالب، لكن لا تتدخل في المنطق المحيط به. انظر إلى المثال التالي الذي يوضح كيف تعمل كتلة ما، والحالة التي لا تعمل فيها كذلك:

{# base.twig #}
{% for post in posts %}
    {% block post %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.body }}</p>
    {% endblock %}
{% endfor %}

إذا أخرجت هذا القالب فإن النتيجة ستكون نفسها سواء استخدمت وسم block أو لا، ذلك أن block التي داخل حلقة for ما هي إلا طريقة لتجعلها قابلة للتخطي بواسطة قالب ابن:

{# child.twig #}
{% extends "base.twig" %}

{% block post %}
    <article>
        <header>{{ post.title }}</header>
        <section>{{ post.text }}</section>
    </article>
{% endblock %}

عند إخراج القالب الابن فإن الحلقة تستخدم الكتلة المعرفة فيه بدلًا من الكتلة المعرفة في القالب الأساس، ثم يقيَّم القالب المنفَّذ بعدها إلى التالي:

{% for post in posts %}
    <article>
        <header>{{ post.title }}</header>
        <section>{{ post.text }}</section>
    </article>
{% endfor %}

لنأخذ مثلًا آخر تكون فيه الكتلة مدرَجة داخل تعليمة if:

{% if posts is empty %}
    {% block head %}
        {{ parent() }}

        <meta name="robots" content="noindex, follow">
    {% endblock head %}
{% endif %}

لا يعرِّف هذا القالب كتلة تعريفًا شرطيًا، على عكس ما قد يظن المرء لأول وهلة، بل يجعل الخرج قابلًا للتخطي بواسطة قالب ابن إذا كان تحقق الشرط، أي كان true. وإذا أردت عرض الخرج عرضًا شرطيًا فاستخدم ما يلي:

{% block head %}
    {{ parent() }}

    {% if posts is empty %}
        <meta name="robots" content="noindex, follow">
    {% endif %}
{% endblock head %}

انظر أيضًا

المصادر