الفرق بين المراجعتين ل"Twig/templates"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(إدخال 2.0 محتوى)
ط
سطر 244: سطر 244:
  
 
== التهريب ==
 
== التهريب ==
قد ترغب أحيانًا -أو تضطر- إلى أن تجعل Twig يتجاهل أجزاءً كان يمكن أن تعالَج على أنها متغيرات أو كتل، فمثلًا إذا استُخدمت البنية الافتراضية وتريد استخدام (<code><nowiki>}}</nowiki></code>)
+
قد ترغب أحيانًا -أو تضطر- إلى أن تجعل Twig يتجاهل أجزاءً كان يمكن أن تعالَج على أنها متغيرات أو كتل، فمثلًا إذا استُخدمت البنية الافتراضية وتريد استخدام (<code><nowiki>}}</nowiki></code>) كسلسلة نصية خام في القالب من غير أن تبدأ متغيرًا جديدًا، فيجب أن تحتال على السلوك الافتراضي، وأسهل طريقة لذلك هي بإخراج محدِّد المتغير (variable delimiter) (<code><nowiki>}}</nowiki></code>) من خلال استخدام تعبير متغير:<syntaxhighlight lang="twig">
 +
{{ '{{' }}
 +
</syntaxhighlight>وبالنسبة للأقسام والكتل الأكبر فمن المنطق أن تحدد الكتلة بوسم [[Twig/verbatim|verbatim]].

مراجعة 18:56، 15 أبريل 2021

تشرح هذه الصفحةُ البنيةَ اللغوية لمحرك القوالب ودلالياته (symantics) وسيكون ذا نفع عظيم كمرجع لأولئك الذين ينشئون قوالب Twig.

القالب هو ملف نصي عادي يستطيع أن يولّد أي صيغة نصية مثل HTML - XML - CSV - LaTex أو غيرها، وليس له امتداد محدد خاص به، فيصلح له امتداد html أو xml مثلًا.

ويحتوي القالب على متغيرات (variables) أو تعابير (expressions)، تُستبدَل القيم بها عند تقييم القالب، ووسوم (tags) تتحكم في منطق القالب. وفيما يلي قالب بسيط يوضح بعض الأساسيات، وسننظر في باقي التفاصيل لاحقًا إن شاء الله.

<!DOCTYPE html>
<html>
    <head>
        <title>My Webpage</title>
    </head>
    <body>
        <ul id="navigation">
        {% for item in navigation %}
            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
        {% endfor %}
        </ul>

        <h1>My Webpage</h1>
        {{ a_variable }}
    </body>
</html>

لدينا نوعان من المحدِّدات (delimiters) هما {% ... %} و {{ ... }}، يُستخدم الأول لتنفيذ تعليمات مثل حلقات for التكرارية، أما الآخر فيخرج نتيجة تعبير ما.

تكامل بيئات التطوير (IDE)

تدعم بيئات تطوير عديدة تمييز التراكيب اللغوية (syntax highlighting) لمحرك Twig والإكمال التلقائي، منها على سبيل المثال:

كذلك فإن TwigFiddle هي خدمة أونلاين تسمح لك بتنفيذ قوالب Twig من المتصفح، وتدعم جميع إصداراته.

المتغيرات

يمرِّر التطبيق المتغيرات إلى القوالب من أجل التعديل داخل القالب، وقد تحتوي المتغيرات على سمات (attributes) أو عناصر تستطيع الوصول إليها، ويعتمد التمثيل البصري للمتغير على التطبيق الذي يوفره.

استخدم النقطة (.) للوصول إلى سمات متغير ما سواء كانت توابع أو خصائص لكائن PHP أو عناصر من مصفوفة PHP.

{{ foo.bar }}

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

التطبيق

بداعي التبسيط، ينفذ foo.bar ما يلي في طبقة PHP:

  • يتحقق إن كان foo مصفوفة وما إذا كان bar عنصرًا صالحًا.
  • فإن لم يكونا كذلك وكان foo كائنًا فيتحقق إن كان bar خاصية صالحة.
  • فإن لم تكن وكان foo كائنًا فيتحقق إن كان bar تابعٌ صالح، حتى لو كان bar هو المنشئ (constructor) فعندئذ استخدم constructor()‎_.
  • فإن لم يكن وكان foo كائنًا فيتحقق أن hasBar تابع صالح.
  • فإن لم يكن فيعيد null.

كذلك فإن Twig يدعم بُنية لغوية محددة للوصول إلى العناصر التي تكون في مصفوفات PHP، وهي foo['bar']‎:

  • تحقق إذا كان foo مصفوفة وbar عنصرًا صالحًا، فإن لم يكن فأعد null.

إذا كان المتغير أو السمة غير موجودان فستحصل على null حين يكون خيار strict_variables على false، أما إذا تم ضبط strict_variables فإن Twig سيرفع خطأ (انظر خيارات البيئة في صفحة واجهة برمجة التطبيقات).

لاحظ أنك إذا أردت أن تصل إلى سمة ديناميكية لمتغير ما، فإن عليك استخدام دالة attribute، وهي مفيدة حين تحتوي السمة على محارف خاصة مثل - التي ستُفسَّر على أنها عامل السالب.

{# equivalent to the non-working foo.data-foo #}
{{ attribute(foo, 'data-foo') }}

المتغيرات العامة (Global Variables)

المتغيرات التالية تكون متاحة دائمًا في القوالب:

  • ‎_self: يشير إلى اسم القالب الحالي.
  • ‎_context: يشير إلى السياق الحالي.
  • ‎_charset: يشير إلى مجموعة المحارف (charset).

ضبط المتغيرات (Setting Variables)

تستطيع تعيين القيم إلى المتغيرات التي داخل كتل الشيفرات، وتستخدم التعيينات وسم set:

{% set foo = 'foo' %}

{% set foo = [1, 2] %}

{% set foo = {'foo': 'bar'} %}

الفلاتر (Filters)

يمكن التعديل على المتغيرات باستخدام الفلاتر، ويفصل بينها وبين المتغيرات برمز الأنبوب |، ويمكن ربط عدة فلاتر معًا في تسلسل واحد، وحينئذ يُطبق خرج أحد تلك الفلاتر على الفلتر الذي يليه. انظر المثال التالي الذي يحذف جميع وسوم HTML من name ويجعلها على نسق العنوان:

{{ name|striptags|title }}

ويكون للفلاتر التي تقبل الوسائط أقواسًا حول الوسائط. المثال التالي يربط بين عناصر قائمة باستخدام فاصلة إنجليزية ,:

{{ list|join(', ') }}

إذا أردت تطبيق فلتر على جزء من الشيفرة فغلِّفه بوسم apply:

{% apply upper %}
    This text becomes uppercase
{% endapply %}

الدوال

يمكن استدعاء الدوال لتوليد المحتوى، وتُستدعى باسمها متبوعًا بقوسين () وقد تحتوي على وسائط. فمثلًا، تعيد دالة range قائمة تحتوي على التقدم الحسابي لأرقام:

{% for i in range(0, 3) %}
    {{ i }},
{% endfor %}

الوسائط المسماة (Named Arguments)

{% for i in range(low=1, high=10, step=2) %}
    {{ i }},
{% endfor %}

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

{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}

{# versus #}

{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}

كما تسمح لك الوسائط المسماة أن تتجاوز بعض الوسائط التي لا تريد تغيير قيمتها الافتراضية:

{# null الوسيط الأول هو صيغة التاريخ التي تكون على الصيغة العالمية للتاريخ إذا تم تمرير #}
{{ "now"|date(null, "Europe/Paris") }}

{# أو تخطى قيمة الصيغة باستخدام وسيط مسمى للمنطقة الزمنية #}
{{ "now"|date(timezone="Europe/Paris") }}

وتستطيع استخدام الوسائط المسماة والموضعية (positional) في استدعاء واحد، لكن يجب أن تكون الوسائط الموضعية في ذلك الاستدعاء قبل الوسائط المسماة:

{{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}

هيكل التحكم

تشير هياكل التحكم إلى الأشياء التي تتحكم في تدفق البرنامج وسيره، مثل التعليمات الشرطية (if/elseif/else) وحلقات for التكرارية، إضافة إلى الكتل مثلًا (blocks)، وتكون هياكل التحكم داخل كتل {% ... %} .

فمثلًا، استخدم وسم for من أجل عرض قائمة من المستخدمين الموجودين في متغير اسمه users :

<h1>Members</h1>
<ul>
    {% for user in users %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>

يمكن استخدام وسم if لاختبار تعبير ما:

{% if users|length > 0 %}
    <ul>
        {% for user in users %}
            <li>{{ user.username|e }}</li>
        {% endfor %}
    </ul>
{% endif %}

اذهب إلى صفحة الوسوم للمزيد عن الوسوم المضمنة.

التعليقات

إذا أردت تحويل جزء من سطر في قالب إلى تعليق فاستخدم {# ...#}، وهذا مفيد في التنقيح (debugging) لاحقًا أو إضافة معلومات لمصممي القوالب الآخرين أو لنفسك:

{# note: disabled template because we no longer use this
    {% for user in users %}
        ...
    {% endfor %}
#}

إدراج قوالب أخرى

تُستخدم دالة include لإدراج قالب ما، وتعيد المحتوى الذي يخرجه ذلك القالب إلى القالب الحالي:

{{ include('sidebar.html') }}

ويجب أن يكون للقوالب المُدرَجة وصول إلى نفس السياق الذي للقالب الذي يحتويهم، وهذا يعني أن أي متغير مُعرّف في القالب الرئيسي سيكون متاحًا في القالب المدرَج أيضًا:

{% for box in boxes %}
    {{ include('render_box.html') }}
{% endfor %}

القالب المدرَج render_box.html له وصول إلى متغير box ، ويعتمد اسم القالب على محمِّله -أي محمل القالب-، فمثلًا، يسمح ‎\Twig\Loader\FilesystemLoader لك أن تصل إلى قوالب أخرى من خلال اسم الملف، فتستطيع الوصول إلى القوالب في الأدلة الفرعية باستخدام شرطة مائلة:

{{ include('sections/articles/sidebar.html') }}

لكن هذا السلوك يعتمد على التطبيق الذي يحتوي Twig.

وراثة القوالب

إن أقوى مزية في Twig هي وراثة القوالب (template inheritance)، وهي تسمح لك ببناء قالب هيكلي أساسي يحتوي على جميع العناصر المشتركة في موقعك، ويعرِّف الوحدات التي تستطيع القوالب الأبناء (child templates) أن تتخطاه. سننظر في مثال الآن للتوضيح.

لنعرِّف قالبًا أساسيًا وليكن 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 هو إخبار محرك القالب أن قالبًا ابنًا قد يتخطى هذه الأجزاء من القالب، والقالب الابن قد يكون شبيهًا بما يلي:

{% 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 to my awesome homepage.
    </p>
{% endblock %}

الوسم extends هو الفيصل هنا إذ يخبر محركَ القالب أن هذا القالب يوسِّع قالبًا آخر، وحين يقيم نظام القالب هذا القالب فإنه يبحث عن القالب الأب أولًا، إذ يجب أن يكون وسم extends هو أول وسم في القالب. وبما أن القالب الابن لا يعرِّف كتلة footer فإن القيمة التي من القالب الأب هي التي تُستخدم. من الممكن أن تُخرِج محتويات الكتلة الأب من خلال استخدام دالة parent، انظر:

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

ستجد أن توثيق وسم extends يصف خصائص أكثر تقدمًا مثل تشعب الكتل والنطاق والوراثة الديناميكية والوراثة الشرطية. كذلك، لاحظ أن Twig يدعم الوراثة المتعددة من خلال إعادة الاستخدام الأفقية بمساعدة وسم use.

تهريب HTML

حين نولد HTML من القوالب فإننا نخاطر باحتمال أن يحتوي متغير على محارف تؤثر على شيفرة HTML الناتجة، وهناك حلان لهذه المشكلة: إما بتهريب (escape) كل متغير يدويًا أو تهريب كل شيء افتراضيًا.

وإن Twig يدعم كلا الحلين، بل إن التهريب الآلي مفعَّل افتراضيًا، ويمكن تعديل استراتيجية التهريب الآلي من خلال خيار autoscape، ويكون الافتراضي على html.

التعامل مع التهريب اليدوي

إذا كان التهريب اليدوي مفعلًا فسيكون تهريب المتغيرات مسؤوليتك أنت إذا احتجت إلى ذلك، وتهرب أي متغير يأتي من مصدر غير موثوق فيه. ونستخدم فلتر escape أو e:

{{ user.username|e }}

يستخدم فلتر escape استراتيجية html افتراضيًا، لكن قد تريد استخدام استراتيجية أخرى استخدامًا صريحًا، وذلك وفقًا لسياق التهريب:

{{ user.username|e('js') }}
{{ user.username|e('css') }}
{{ user.username|e('url') }}
{{ user.username|e('html_attr') }}

التعامل مع التهريب الآلي

تستطيع تحديد جزء من قالب ما ليتم تهريبه آليًا سواء كان التهريب الآلي مفعلًا أم لا، وذلك باستخدام وسم autoscape:

{% autoescape %}
    HTML سيهرّب كل شيء في هذه الكتلة باستخدام استراتيجية 
{% endautoescape %}

يستخدم التهريب الآلي خطة تهريب html افتراضيًا، أما إذا كنت تُخرِج متغيرات في سياقات أخرى فستحتاج إلى أن تهربها صراحة بخطة التهريب المناسبة:

{% autoescape 'js' %}
   JS سيُهرَّب كل شيء آليًا في هذه الكتلة باستخدام خطة
{% endautoescape %}

التهريب

قد ترغب أحيانًا -أو تضطر- إلى أن تجعل Twig يتجاهل أجزاءً كان يمكن أن تعالَج على أنها متغيرات أو كتل، فمثلًا إذا استُخدمت البنية الافتراضية وتريد استخدام (}}) كسلسلة نصية خام في القالب من غير أن تبدأ متغيرًا جديدًا، فيجب أن تحتال على السلوك الافتراضي، وأسهل طريقة لذلك هي بإخراج محدِّد المتغير (variable delimiter) (}}) من خلال استخدام تعبير متغير:

{{ '{{' }}

وبالنسبة للأقسام والكتل الأكبر فمن المنطق أن تحدد الكتلة بوسم verbatim.