الفرق بين المراجعتين لصفحة: «Twig/api»

من موسوعة حسوب
إدخال 2.1 محتوى
طلا ملخص تعديل
 
(8 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:Twig للمطورين}}</noinclude>
<noinclude>{{DISPLAYTITLE:محرك Twig للمطورين}}</noinclude>
هذ{{DISPLAYTITLE:Twig للمطورين}}ه الصفحة تشرح واجهة برمجة التطبيقات (API) لمحرك القوالب Twig، وليس لغة القالب نفسه، وستكون مفيدة كمرجع لأولئك الذين يستخدمون واجهة القالب للتطبيق، وليس للذين ينشؤون قوالب  Twig.
تشرح هذه الصفحة واجهة برمجة التطبيقات API لمحرك القوالب Twig، وستكون مفيدة كمرجع لأولئك الذين يستخدمون واجهة القالب للتطبيق، فهي لا تشرح لغة القالب نفسه، وليست للذين ينشؤون قوالب  Twig.
 
== مقدمة ==
== مقدمة ==
يستخدم Twig كائنًا مركزيًا يسمى البيئة -من الصنف ‎<code>\Twig\Environment</code>، وتُستخدم النُسخ (instances) التي لهذا الصنف في تخزين الإعدادات والتوسعات (extensions) وتحميل القوالب. وتنشئ أغلب التطبيقات كائن  ‎<code>\Twig\Environment</code> واحد فقط أثناء تهيئة التطبيق (app initialization) وتستخدم ذلك في تحميل القوالب، وقد يفيدنا أحيانًا أن يكون لدينا عدة بيئات جنبًا إلى جنب لها إعدادات مختلفة. والطريقة المعتادة لإعداد Twig كي يحمِّل القوالب لتطبيق ما تكون غالبًا كما يلي:<syntaxhighlight lang="twig">
يستخدم Twig كائنًا مركزيًا يسمى البيئة -من الصنف ‎<code>\Twig\Environment</code>، وتُستخدم النُسخ instances التي لهذا الصنف في تخزين الإعدادات والتوسعات extensions وتحميل القوالب. وتنشئ أغلب التطبيقات كائن  ‎<code>\Twig\Environment</code> واحد فقط أثناء تهيئة التطبيق app initialization وتستخدمه في تحميل القوالب، وقد يفيدنا أحيانًا أن يكون لدينا عدة بيئات جنبًا إلى جنب لها إعدادات مختلفة. تكون الطريقة المعتادة لإعداد Twig كي يحمِّل القوالب لتطبيق ما كما يلي غالبًا:<syntaxhighlight lang="php">
require_once '/path/to/vendor/autoload.php';
require_once '/path/to/vendor/autoload.php';


سطر 10: سطر 9:
     'cache' => '/path/to/compilation_cache',
     'cache' => '/path/to/compilation_cache',
]);
]);
</syntaxhighlight>هذا ينشئ بيئة قالب بالإعدادات الافتراضية، ومحمِّل يبحث عن القوالب في المجلد <code>/path/to/templates/</code> ، وتوجد عدة محملات متاحة كما تستطيع كتابة المحمل الخاص بك إذا أردت تحميل قوالب من قاعدة بيانات أو مصادر أخرى.
</syntaxhighlight>ينشئ هذا بيئةَ قالب بالإعدادات الافتراضية، ومحمِّل يبحث عن القوالب في المجلد <code>/path/to/templates/</code>، وتوجد عدة محملات متاحة، كما تستطيع كتابة المحمل الخاص بك إذا أردت تحميل قوالب من قاعدة بيانات أو مصادر أخرى.


لاحظ أن الوسيط الثاني للبيئة ما هو إلا مصفوفة من الخيارات، فالخيار  cache مثلًا هو مجلد لذاكرة التصريف (compilation cache) حيث يحتفظ Twig بالقوالب المصرَّفة لتجنب مرحلة التحليل (parsing) للطلبات التالية، ويختلف هذا كثيرًا عن الذاكرة المؤقتة التي تريد إضافتها للقوالب المقيَّمة، فلتلك يمكن استخدام أي مكتبة ذاكرة مؤقتة للغة PHP.
لاحظ أن الوسيط الثاني للبيئة ما هو إلا مصفوفة من الخيارات، فالخيار  <code>cache</code> مثلًا هو مجلد لذاكرة التصريف compilation cache حيث يحتفظ Twig بالقوالب المصرَّفة لتجنب مرحلة التحليل parsing للطلبات التالية، ويختلف هذا كثيرًا عن الذاكرة المؤقتة التي تريد إضافتها للقوالب المقيَّمة، فلتلك يمكن استخدام أي مكتبة ذاكرة مؤقتة للغة [[PHP]].


== إخراج القوالب (Rendering Templates) ==
== تصيير القوالب Rendering Templates ==
إذا أردت تحميل قالب من بيئة Twig فاستدع التابع load() الذي يعيد نسخة من \Twig\TemplateWrapper:<syntaxhighlight lang="twig">
إذا أردت تحميل قالب من بيئة Twig فاستدع التابع <code>load()‎</code> الذي يعيد نسخة من ‎<code>\Twig\TemplateWrapper</code>:<syntaxhighlight lang="php">
$template = $twig->load('index.html');
$template = $twig->load('index.html');


</syntaxhighlight>ولإخراج القالب مع بعض المتغيرات، استدع التابع render(): <syntaxhighlight lang="twig">
</syntaxhighlight>ولتصيير القالب مع بعض المتغيرات، استدع التابع <code>render()‎</code>: <syntaxhighlight lang="php">
echo $template->render(['the' => 'variables', 'go' => 'here']);
echo $template->render(['the' => 'variables', 'go' => 'here']);


</syntaxhighlight>لاحظ أن التابع display() ما هو إلا اختصار لكي نحصل على القالب المخرَج (rendered template). كذلك يمكنك تحميل القالب وإخراجه في خطوة واحدة:<syntaxhighlight lang="twig">
</syntaxhighlight>لاحظ أن التابع <code>display()‎</code> ما هو إلا اختصار لكي نحصل على القالب المصيَّر rendered template. كذلك يمكنك تحميل القالب وتصييره في خطوة واحدة كما يلي:<syntaxhighlight lang="php">
echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']);
echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']);


</syntaxhighlight>وإذا عرَّف القالب وحدات فيمكن إخراجها منفردة من خلال استدعاء renderBlock():<syntaxhighlight lang="twig">
</syntaxhighlight>وإذا عرَّف القالب وحدات فيمكن تصييرها منفردة من خلال استدعاء <code>renderBlock()‎</code>:<syntaxhighlight lang="php">
echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);


سطر 30: سطر 29:


== خيارات البيئة ==
== خيارات البيئة ==
يمكن أن تمرر مصفوفة من الخيارات كوسيط ثاني للمنشئ (constructor) عند إنشاء نسخة جديدة من \Twig\Environment: <syntaxhighlight lang="twig">
يمكن أن تمرر مصفوفة من الخيارات كوسيط ثاني للمنشئ constructor عند إنشاء نسخة جديدة من ‎<code>\Twig\Environment</code>: <syntaxhighlight lang="php">
$twig = new \Twig\Environment($loader, ['debug' => true]);
$twig = new \Twig\Environment($loader, ['debug' => true]);


</syntaxhighlight>ويكون لدينا ما يلي من الخيارات المتاحة:
</syntaxhighlight>ويكون لدينا ما يلي من الخيارات المتاحة:


* debug الثنائي: حين يتحقق -أي يكون true- فإن القوالب المولَّدة يكون لها التابع __toString() الذي تستطيع استخدامه لعرض العقد المولَّدة، ويكون الافتراضي على false.
* <code>debug</code> البولياني: حين يتحقق -أي يكون <code>true</code>- فإن القوالب المولَّدة يكون لها التابع ‎<code>__toString()‎</code> الذي تستطيع استخدامه لعرض العقد المولَّدة، ويكون الافتراضي على <code>false</code>.
* السلسلة النصية charset: يكون الافتراضي لها على utf-وتُستخدم مجموعة المحارف (charset) من قِبل القوالب.
* السلسلة النصية <code>charset</code>: يكون الافتراضي لها على <code>utf-8</code>، وتُستخدم مجموعة المحارف charset من قِبل القوالب.
* السلسلة النصية cache أو false: مسار مطلق حيث تُخزَّن القوالب المصرَّفة، أو false لتعطيل التخزين المؤقت وهو الافتراضي.
* السلسلة النصية <code>cache</code> أو <code>false</code>: مسار مطلق حيث تُخزَّن القوالب المصرَّفة، أو <code>false</code> لتعطيل التخزين المؤقت وهو الافتراضي.
* الثنائي auto_reload: من المفيد عند استخدام Twig أن تعيد تصريف القالب كلما تغيرت الشيفرة المصدرية، وإذا لم توفر قيمة لخيار auto_reload فإنها ستُحدد تلقائيًا بناء على قيمة debug.
* الثنائي <code>auto_reload</code>: من المفيد عند استخدام Twig أن تعيد تصريف القالب كلما تغيرت الشيفرة المصدرية، وإذا لم توفر قيمة لخيار <code>auto_reload</code> فإنها ستُحدد تلقائيًا بناء على قيمة <code>debug</code>.
* الثنائي strict_variables: إذا كان false فسيتجاهل Twig المتغيرات غير الصالحة بصمت -وهي المتغيرات و/أو السمات/التوابع غير الموجودة-، ويستبدل قيمة غير معرفة null بها. أما حين يكون true فإن Twig يرفع اعتراضًا (exception). وافتراضي هذا الخيار يكون false.
* <code>strict_variables</code> البولياني: إذا كان <code>false</code> فسيتجاهل Twig المتغيرات غير الصالحة بصمت -وهي المتغيرات و/أو السمات/التوابع غير الموجودة-، ويستبدل قيمة غير معرفة <code>null</code> بها. أما حين يكون <code>true</code> فإن Twig يرفع اعتراضًا exception. وافتراضي هذا الخيار يكون <code>false</code>.
* السلسلة النصية autoescape: يضع هذا الخيار خطة التهريب التلقائي الافتراضية (name ، html ، js ، css ، url ، html_attr ، أو استدعاء PHP خلفي يأخذ "اسم الملف" للقالب ويعيد خطة التهريب لاستخدامها، ولا يمكن أن يكون الاستدعاء الخلفي اسم دالة لئلا يتعارض مع خطط التهريب المضمنة). فاضبط خطة التهريب إذًا لتكون false لتعطيل التهريب التلقائي. تحدد خطةُ التهريب name خطةَ التهريب التي يجب استخدامها لقالب مبني على توسيع اسم ملف القالب، ولا تتسبب هذه الخطة في أي حمل زائد (overhead) أثناء التشغيل لأن التهريب التلقائي يتم في وقت التصريف.
* السلسلة النصية <code>autoescape</code>: يضع هذا الخيار خطة التهريب التلقائي الافتراضية <code>name</code> ، <code>html</code> ، <code>js</code> ، <code>css</code> ، <code>url</code> ، <code>html_attr</code> ، أو استدعاء PHP خلفي callback يأخذ "اسم الملف" للقالب ويعيد خطة التهريب لاستخدامها، ولا يمكن أن يكون الاستدعاء الخلفي اسم دالة لئلا يتعارض مع خطط التهريب المضمنة، فاضبط خطة التهريب إذًا لتكون <code>false</code> لتعطيل التهريب التلقائي. تحدد خطةُ التهريب <code>name</code> خطةَ التهريب التي يجب استخدامها لقالب مبني على توسعة اسم ملف القالب، ولا تتسبب هذه الخطة في أي حمل زائد overhead أثناء التشغيل لأن التهريب التلقائي يتم في وقت التصريف.
* العدد optimizations: راية توضح أي التحسينات التي يجب تطبيقها، ويكون الافتراضي لهذا الخيار هو -حيث تكون جميع التحسينات مفعلة، وإذا أردت تعطيلها فاجعله على 0.
* عدد التحسينات <code>optimizations</code>: راية توضح أي التحسينات التي يجب تطبيقها، ويكون الافتراضي لهذا الخيار هو ‎<code>-1</code>، حيث تكون جميع التحسينات مفعلة، وإذا أردت تعطيلها فاجعله على <code>0</code>.


== المحملات (Loaders) ==
== المحملات Loaders ==
تكون المحملات مسؤولة عن تحميل القوالب من مصادر مثل نظام الملفات.
تكون المحملات مسؤولة عن تحميل القوالب من مصادر مثل نظام الملفات.


=== ذاكرة التصريف المؤقتة (Compilation Cache) ===
=== ذاكرة التصريف المؤقتة Compilation Cache ===
تستطيع جميع محملات القوالب أن تخزن القوالب المصرَّفة في نظام الملفات من أجل الاستخدام المستقبلي، وهذا يسرع Twig كثيرًا بما أن القوالب تُصرَّف مرة واحدة فقط.
تستطيع جميع محملات القوالب أن تخزن القوالب المصرَّفة في نظام الملفات من أجل الاستخدام المستقبلي، وهذا يسرع Twig كثيرًا بما أن القوالب تُصرَّف مرة واحدة فقط.


=== المحملات المضمنة (Built-in Loaders) ===
=== المحملات المضمنة Built-in Loaders ===
فيما يلي قائمة بالمحمٍّلات المضمنة في Twig:
فيما يلي قائمة بالمحمٍّلات المضمنة في Twig:


==== <code>\Twig\Loader\FilesystemLoader</code> ====
==== <code>\Twig\Loader\FilesystemLoader</code> ====
يحمل <code>\Twig\Loader\FilesystemLoader</code> القوالب من نظام التشغيل، ويستطيع العثور على القوالب الموجودة في المجلدات التي في نظام التشغيل، وهو الطريقة المفضلة لتحميلها: <syntaxhighlight lang="twig">
يحمل القوالب من نظام التشغيل، ويستطيع العثور عليها إن كانت فيه، وهو الطريقة المفضلة لتحميلها: <syntaxhighlight lang="twig">
$loader = new \Twig\Loader\FilesystemLoader($templateDir);
$loader = new \Twig\Loader\FilesystemLoader($templateDir);
</syntaxhighlight>كما يبحث أيضًا في القوالب التي في مصفوفة من المجلدات:<syntaxhighlight lang="twig">
</syntaxhighlight>كما يبحث أيضًا في القوالب التي في مصفوفة من المجلدات:<syntaxhighlight lang="twig">
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
</syntaxhighlight>وسيبحث Twig أولًا بهذه الإعدادات عن القوالب التي في $templateDir1 وإذا لم تكن موجودة فسيرجع للبحث عنها في $templateDir2. تستطيع إضافة المسارات أو إسباقها بشيء من خلال التابعيْن addPath() و prependPath():  <syntaxhighlight lang="twig">
</syntaxhighlight>وسيبحث Twig أولًا بهذه الإعدادات عن القوالب التي في ‎<code>$templateDir1</code> وإذا لم تكن موجودة فسيرجع للبحث عنها في ‎<code>$templateDir2</code>. تستطيع إضافة المسارات أو إسباقها بشيء من خلال التابعيْن <code>addPath()‎</code> و <code>prependPath()‎</code>:  <syntaxhighlight lang="twig">
$loader->addPath($templateDir3);
$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);
$loader->prependPath($templateDir4);
</syntaxhighlight>كما يدعم محمل نظام الملفات القوالب ذات فضاءات الأسماء، وهذا يسمح لك بجمع قوالبك تحت فضاءات أسماء مختلفة يكون لها مسارات قوالب خاصة بها.
</syntaxhighlight>كما يدعم محمل نظام الملفات القوالب ذات فضاءات الأسماء namespaced templates، وهذا يسمح لك بجمع قوالبك تحت فضاءات أسماء مختلفة يكون لها مسارات قوالب خاصة بها.


إذا استخدمت التوابع setPath() و addPAth() و prependPath() فحدد فضاء الاسم كوسيط ثاني، فإذا لم تحدد ذلك فإن هذه التوابع تتصرف على فضاء الاسم الرئيسي:<syntaxhighlight lang="twig">
إذا استخدمت التوابع <code>setPath()‎</code> و <code>addPAth()‎</code> و <code>prependPath()‎</code> فحدد فضاء الاسم كوسيط ثاني، فإذا لم تحدد ذلك فإن هذه التوابع تتصرف على فضاء الاسم الرئيسي:<syntaxhighlight lang="twig">
$loader->addPath($templateDir, 'admin');
$loader->addPath($templateDir, 'admin');


</syntaxhighlight>يمكن الوصول إلى القوالب ذات فضاءات الأسماء من خلال الترميز الخاص (@namespace_name/template_path):<syntaxhighlight lang="twig">
</syntaxhighlight>يمكن الوصول إلى القوالب ذات فضاءات الأسماء من خلال الترميز الخاص ‎<code>@namespace_name/template_path‎</code>:<syntaxhighlight lang="twig">
$twig->render('@admin/index.html', []);
$twig->render('@admin/index.html', []);


</syntaxhighlight>يدعم \Twig\Loader\FilesystemLoader المسارات المطلقة والنسبية، ويفضَّل استخدام المسارات النسبية لأنها تجعل مفاتيح الذاكرة المؤقتة (cache keys) مستقلة عن مجلد الجذر للمشروع، فهي تسمح مثلًا بتهيئة الذاكرة المؤقتة (warming) من خادم بناء حيث يكون المجلد مختلفًا عن المستخدم في خوادم العمل الحقيقية:<syntaxhighlight lang="twig">
</syntaxhighlight>يدعم ‎<code>\Twig\Loader\FilesystemLoader</code> المسارات المطلقة والنسبية، ويفضَّل استخدام المسارات النسبية لأنها تجعل مفاتيح الذاكرة المؤقتة cache keys مستقلة عن مجلد الجذر للمشروع، فهي تسمح مثلًا بتهيئة warming الذاكرة المؤقتة من خادم بناء حيث يكون المجلد مختلفًا عن المستخدم في خوادم العمل الحقيقية:<syntaxhighlight lang="twig">
$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');
$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');


</syntaxhighlight>لاحظ أن Twig يستخدم getcwd() للمسارات النسبية عند عدم تمرير المسار الجذر كوسيط ثاني.
</syntaxhighlight>لاحظ أن Twig يستخدم <code>getcwd()‎</code> للمسارات النسبية عند عدم تمرير المسار الجذر كوسيط ثاني.


==== \Twig\Loader\ArrayLoader ====
==== ‎<code>\Twig\Loader\ArrayLoader</code> ====
يحمِّل \Twig\Loader\ArrayLoader قالبًا من مصفوفة PHP، وتُمرَّر كمصفوفة سلاسل نصية مقيدة بأسماء القوالب:<syntaxhighlight lang="twig">
يحمِّل قالبًا من مصفوفة PHP، وتُمرَّر كمصفوفة سلاسل نصية مقيدة بأسماء القوالب:<syntaxhighlight lang="twig">
$loader = new \Twig\Loader\ArrayLoader([
$loader = new \Twig\Loader\ArrayLoader([
     'index.html' => 'Hello {{ name }}!',
     'index.html' => 'Hello {{ name }}!',
سطر 83: سطر 82:
</syntaxhighlight>وهذا المحمِّل مفيد جدًا في اختبار الوحدات، كما يمكن استخدامه للمشاريع الصغيرة التي يكون من المنطقي فيها تخزين جميع القوالب في ملف PHP واحد.
</syntaxhighlight>وهذا المحمِّل مفيد جدًا في اختبار الوحدات، كما يمكن استخدامه للمشاريع الصغيرة التي يكون من المنطقي فيها تخزين جميع القوالب في ملف PHP واحد.


وعند استخدام محمِّل Array مع آلية تخزين مؤقت فيجب أن تعلم أن مفتاح الذاكرة الجديد يولَّد في كل مرة يتغير فيها محتوى القالب إذ أن مفتاح الذاكرة المؤقتة هو نفسه الشيفرة المصدرية للقالب، فإذا أردت الحفاظ على ذاكرتك المؤقتة من أن تخرج عن السيطرة فربما تود إخلاء الذاكرة القديمة بنفسك.
وعند استخدام محمِّل <code>Array</code> مع آلية تخزين مؤقت فيجب أن تعلم أن مفتاح الذاكرة الجديد يولَّد في كل مرة يتغير فيها محتوى القالب، إذ أن مفتاح الذاكرة المؤقتة هو نفسه الشيفرة المصدرية للقالب، فإذا أردت الحفاظ على ذاكرتك المؤقتة من الخروج عن السيطرة فربما تود إخلاء الذاكرة القديمة بنفسك.


==== \Twig\Loader\ChainLoader ====
==== ‎<code>\Twig\Loader\ChainLoader</code> ====
يفوِّض \Twig\Loader\ChainLoader مهمة تحميل القوالب إلى محمِّلات أخرى:<syntaxhighlight lang="twig">
يفوِّض هذا المحمِّل مهمة تحميل القوالب إلى محمِّلات أخرى:<syntaxhighlight lang="php">
1
2
3
4
5
6
7
8
9
10
11
$loader1 = new \Twig\Loader\ArrayLoader([
$loader1 = new \Twig\Loader\ArrayLoader([
     'base.html' => '{% block content %}{% endblock %}',
     'base.html' => '{% block content %}{% endblock %}',
سطر 109: سطر 97:


$twig = new \Twig\Environment($loader);
$twig = new \Twig\Environment($loader);
</syntaxhighlight>يحاول Twig مع كل محمِّل عند البحث عن قالب ما، ويعيد بمجرد العثور على قالب، وعند إخراج قالب index.html من المثال السابق فإن Twig سيحمله باستخدام $loader2، على عكس قالب base.html الذي سيحمَّل من $loader1.
</syntaxhighlight>يحاول Twig مع كل محمِّل عند البحث عن قالب ما، ويعيد بمجرد العثور على قالب، وعند إخراج قالب <code>index.html</code> من المثال السابق فإن Twig سيحمله باستخدام ‎<code>$loader2</code>، على عكس قالب <code>base.html</code> الذي سيحمَّل من ‎<code>$loader1</code>.


لاحظ أنك تستطيع إضافة المحمِّلات باستخدام التابع addLocker().
لاحظ أنك تستطيع إضافة المحمِّلات باستخدام التابع <code>addLocker()‎</code>.


=== إنشاء المحمِّل الخاص بك ===
=== إنشاء المحمِّل الخاص بك ===
جميع المحمِّلات تستخدم \Twig\Loader\LoaderInterface:<syntaxhighlight lang="twig">
تستخدم جميع المحمِّلات ‎<code>\Twig\Loader\LoaderInterface</code>:<syntaxhighlight lang="php">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
interface \Twig\Loader\LoaderInterface
interface \Twig\Loader\LoaderInterface
{
{
سطر 205: سطر 148:
     public function exists($name);
     public function exists($name);
}
}
</syntaxhighlight>التابع isFresh() يجب أن يتحقق -يعيد true- إذا كان القالب المخزَّن حاليًا جديدًا، إذا أُعطي آخر وقت تعديل عليه، وإلا فإنه يعيد false. كذلك،  يجب أن يعيد التابع getSourceContext() نسخة من \Twig\source.
</syntaxhighlight>يجب أن يتحقق التابع <code>isFresh()‎</code>  -يعيد <code>true</code>- إذا أُعطي آخر وقت تعديل عليه مما إذا كان القالب المخزَّن جديدًا، وإلا فإنه يعيد <code>false</code>. كذلك،  يجب أن يعيد التابع <code>getSourceContext()‎</code> نسخة من ‎<code>\Twig\source</code>.


== استخدام التوسعات (Extensions) ==
== استخدام التوسعات Extensions ==
توسعات Twig هي حزم تضيف مزايا جديدة إليه، وتستطيع تسجيل توسيع من خلال التابع addExtension():<syntaxhighlight lang="twig">
توسعات Twig هي حزم تضيف مزايا جديدة إليه، وتستطيع تسجيل توسعة من خلال التابع <code>addExtension()‎</code>:<syntaxhighlight lang="php">
$twig->addExtension(new \Twig\Extension\SandboxExtension());  
$twig->addExtension(new \Twig\Extension\SandboxExtension());  
</syntaxhighlight>وتأتي التوسعات التالية مع Twig:
</syntaxhighlight>وتأتي التوسعات التالية مع Twig:


* TwigExtensionCoreExtension: تعرِّف جميع المزايا الأساسية لـ Twig.
* <code>TwigExtensionCoreExtension</code>: تعرِّف جميع المزايا الأساسية لـ Twig.
* TwigExtensionDebugExtension: تعرِّف دالة dump للمساعدة في تنقيح متغيرات القالب.
* <code>TwigExtensionDebugExtension</code>: تعرِّف دالة <code>dump</code> للمساعدة في تنقيح متغيرات القالب.
* TwigExtensionEscaperExtension: تضيف تهريبًا تلقائيًا للخرج واحتمالية تهريب أو إلغاء تهريب كتل من الشيفرة.
* <code>TwigExtensionEscaperExtension</code>: تضيف تهريبًا تلقائيًا للخرج واحتمالية تهريب أو إلغاء تهريب كتل من الشيفرة.
* TwigExtensionSandboxExtension: تضيف وضع صندوق الاختبار إلى بيئة Twig الافتراضية لتجعلها أكثر أمانًا لتقييم الشيفرات غير الموثوق فيها.
* <code>TwigExtensionSandboxExtension</code>: تضيف وضع صندوق الاختبار إلى بيئة Twig الافتراضية لتجعلها أكثر أمانًا لتقييم الشيفرات غير الموثوق فيها.
* TwigExtensionProfilerExtension: تفعِّل المحلل (profiler) المضمن في Twig.
* <code>TwigExtensionProfilerExtension</code>: تفعِّل المحلل profiler المضمن في Twig.
* TwigExtensionOptimizerExtension: تحسِّن شجرة العُقد قبل التصريف.
* <code>TwigExtensionOptimizerExtension</code>: تحسِّن شجرة العُقد قبل التصريف.
* TwigExtensionStringLoaderExtension: تعرِّف دالة template_from_string لتسمح بتحميل القوالب من سلسلة نصية في قالب ما.
* <code>TwigExtensionStringLoaderExtension</code>: تعرِّف دالة <code>template_from_string</code> لتسمح بتحميل القوالب من سلسلة نصية في قالب ما.


وأما توسعات القلب (Core) و المهرِّب (Escaper) و المحسِّن (Optimizer) فتكون مسجلة افتراضيًا.
وأما توسعات النواة Core و المهرِّب Escaper و المحسِّن Optimizer فتكون مسجلة افتراضيًا.


== التوسعات المضمنة ==
== التوسعات المضمنة ==
يشرح هذا القسم المزايا المضافة بواسطة التوسعات المضمنة، ربما تود قراءة صفحة [[Twig/advanced|توسعة Twig]] لتعلم كيف تنشئ توسعاتك الخاصة بك.
يشرح هذا القسم المزايا المضافة بواسطة التوسعات المضمنة built-in extensions إلى Twig، ربما تود قراءة صفحة [[Twig/advanced|توسعة Twig]] لتعلم كيف تنشئ توسعاتك الخاصة بك.


=== توسيع Core ===
=== Core ===
يعرِّف توسيع core جميع المزايا الأساسية في Twig:
يعرِّف التوسعة أو الإضافة <code>core</code> جميع المزايا الأساسية في Twig:


* [[Twig/tags/apply|الوسوم (Tags)]].
* [[Twig/tags|الوسوم Tags]]
* [[Twig/filters/abs|الفلاتر (Filters)]].
* [[Twig/filters|المرشحات Filters]]
* [[Twig/functions/attribute|الدوال (Functions)]].
* [[Twig/functions|الدوال Functions]]
* [[Twig/tests/constant|الاختبارات (Tests)]].
* [[Twig/tests|الاختبارات Tests]]


=== توسيع Escaper ===
=== Escaper ===
يضيف توسيع escaper التهريب الآلي للخرج إلى Twig، ويعرِّف وسمًا هو autoescape، وفلترًا هو raw. وتستطيع تشغيل أو إيقاف خطة تهريب الخرج العامة عند إنشاء توسيع المهرِّب:<syntaxhighlight lang="twig">
تضيف التوسعة <code>escaper</code> التهريب التلقائي للخرج إلى Twig، وتعرِّف وسمًا هو <code>[[Twig/autoescape|autoescape]]</code>، ومرشحًا هو <code>[[Twig/raw|raw]]</code>، وتستطيع تشغيل أو إيقاف خطة تهريب الخرج العامة عند إنشاء توسعة المهرِّب:<syntaxhighlight lang="php">
$escaper = new \Twig\Extension\EscaperExtension('html');
$escaper = new \Twig\Extension\EscaperExtension('html');
$twig->addExtension($escaper);
$twig->addExtension($escaper);
</syntaxhighlight>وتهرَّب جميع المتغيرات باستخدام خطة تهريب html إذا ضبط التوسيع على html، ما عدا التي تستخدم فلتر raw:<syntaxhighlight lang="twig">
</syntaxhighlight>وتهرَّب جميع المتغيرات باستخدام خطة تهريب <code>html</code> إذا ضبط التوسعة على <code>html</code>، ما عدا التي تستخدم مرشح [[Twig/raw|<code>raw</code>]]:<syntaxhighlight lang="twig">
{{ article.to_html|raw }}
{{ article.to_html|raw }}


</syntaxhighlight>كما تستطيع تغيير وضع التهريب محليًا من خلال استخدام وسم autoescape:<syntaxhighlight lang="twig">
</syntaxhighlight>كما تستطيع تغيير وضع التهريب محليًا من خلال استخدام وسم [[Twig/autoescape|<code>autoescape</code>]]:<syntaxhighlight lang="twig">
{% autoescape 'html' %}
{% autoescape 'html' %}
     {{ var }}
     {{ var }}
سطر 246: سطر 189:
     {{ var|escape }}  {# var won't be double-escaped #}
     {{ var|escape }}  {# var won't be double-escaped #}
{% endautoescape %}
{% endautoescape %}
</syntaxhighlight>لكن انتبه إلى أن وسم autoescape ليس له تأثير على الملفات المضمنة.
</syntaxhighlight>لكن انتبه إلى أن وسم [[Twig/autoescape|<code>autoescape</code>]] ليس له تأثير على الملفات المضمنة. وتطبَّق قواعد التهريب كما يلي:


تطبَّق قواعد التهريب كما يلي:
* القيم مصنفة النوع Literals وهي الأعداد الصحيحة، القيم البوليانية، المصفوفات، ...إلخ المستخدمة في القالب مباشرة كمتغيرات أو وسائط لمرشحات لا تُهرَّب تلقائيًا أبدًا:
 
* القيم مصنفة النوع (الأعداد الصحيحة، القيم البوليانية، المصفوفات، ..) المستخدمة في القالب مباشرة كمتغيرات أو وسائط لفلاتر لا تُهرَّب تلقائيًا أبدًا:
<syntaxhighlight lang="twig">
<syntaxhighlight lang="twig">
{{ "Twig<br/>" }} {# لن تهرَّب #}
{{ "Twig<br/>" }} {# لن تهرَّب #}
سطر 258: سطر 199:
</syntaxhighlight>
</syntaxhighlight>


* التعابير التي تكون نتيجتها قيمة مصنفة النوع أو متغير آمن لا تهرَّب تلقائيًا كذلك:<syntaxhighlight lang="twig">
* التعابير التي تكون نتيجتها قيمة مصنفة النوع أو متغير آمن لا تهرَّب تلقائيًا كذلك:
<syntaxhighlight lang="twig">
{{ foo ? "Twig<br/>" : "<br/>Twig" }} {# لن تهرَّب #}
{{ foo ? "Twig<br/>" : "<br/>Twig" }} {# لن تهرَّب #}


سطر 268: سطر 210:
{{ foo ? text|raw : "<br/>Twig" }} {# لن تهرَّب #}
{{ foo ? text|raw : "<br/>Twig" }} {# لن تهرَّب #}
</syntaxhighlight>
</syntaxhighlight>
*
* تحوَّل الكائنات التي بها التابع ‎<code>_tostring</code> إلى سلاسل نصية وتهرَّب، ويمكنك تحديد بعض الأصناف أو/و الواجهات لتكون آمنة لبعض الخطط من خلال <code>EscaperExtension::addSafeClass()‎</code> كما يلي:
<syntaxhighlight lang="twig">
// HTML ليكون آمنًا لخطة Foo حدد كائن صنف
$escaper->addSafeClass('Foo', ['html']);
 
// HTML ليكون آمنًا لخطة Foo حدد كائن واجهة
$escaper->addSafeClass('FooInterface', ['html']);
 
// JS و HTML ليكون آمنًا لخطتي Foo حدد كائن صنف
$escaper->addSafeClass('Foo', ['html', 'js']);
 
// ليكون آمنًا لجميع الخطط Foo حدد كائن صنف
$escaper->addSafeClass('Foo', ['all']);
</syntaxhighlight>
* يطبَّق التهريب قبل الطباعة وبعد تطبيق جميع المرشحات الأخرى:
<syntaxhighlight lang="twig">
{{ var|upper }} {# {{ var|upper|escape }} مكافئ لـ #}
 
</syntaxhighlight>
* يجب أن يُستخدم مرشح  <code>raw</code> في نهاية سلسلة المرشحات فقط:
<syntaxhighlight lang="twig">
{{ var|raw|upper }} {# سيهرَّب #}
 
{{ var|upper|raw }} {# لن يهرَّب #}
</syntaxhighlight>
لا يطبَّق التهريب التلقائي إذا كان المرشح الأخير في السلسلة محددًا على أنه آمن للسياق الحالي -<code>html</code> مثلًا أو <code>JS</code>-، فمثلًا يكون كل من <code>escape</code> و <code>escape('html')</code> آمنين لـ <code>html</code>، ويكون <code>escape('js')</code> آمنًا لجافاسكربت، ويكون <code>raw</code> آمنًا لأي شيء.<syntaxhighlight lang="twig">
{% autoescape 'js' %}
    {{ var|escape('html') }} {# will be escaped for HTML and JavaScript #}
    {{ var }} {# will be escaped for JavaScript #}
    {{ var|escape('js') }} {# won't be double-escaped #}
{% endautoescape %}
</syntaxhighlight>
 
* لاحظ أن التهريب التلقائي به بعض القيود بما أن التهريب يطبق على التعابير بعد تقييمها، فمثلًا لن يعطيك <code><nowiki>{{ foo|raw ~ bar }}</nowiki></code> النتيجة التي تريدها عند العمل مع ضم ما concatenation إذ أن التهريب يطبق على نتيجة الضم وليس على المتغيرات منفردة، وعليه لن يكون لمرشح <code>raw</code> أي تأثير هنا.
 
=== Sandbox ===
يمكن استخدام توسعة صندوق الاختبار <code>sandbox</code> لتقييم الشيفرات غير الموثوق فيها إذ يُمنع الوصول إلى السمات والتوابع غير الآمنة، ويدار نظام الأمان في صندوق الاختبار من خلال نسخة سياسة policy instance، ويأتي Twig افتراضيًا بصنف سياسة واحد هو ‎<code>\Twig\Sandbox\SecurityPolicyK</code>، ويسمح لك هذا الصنف بوضع بعض الوسوم والمرشحات والخصائص والتوابع في القائمة البيضاء المسموح بها: <syntaxhighlight lang="php">
$tags = ['if'];
$filters = ['upper'];
$methods = [
    'Article' => ['getTitle', 'getBody'],
];
$properties = [
    'Article' => ['title', 'body'],
];
$functions = ['range'];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
</syntaxhighlight>ووفقًا للإعدادات السابقة فإن سياسة الأمان ستسمح باستخدام وسم <code>[[Twig/if|if]]</code> ومرشح <code>[[Twig/upper|upper]]</code> فقط، كما لن يسمح للقوالب أن تستدعي إلا التابعين <code>getTitle()‎</code> و <code>getBody()‎</code> على كائنات <code>Article</code>، وكذلك الخاصيتين <code>title</code> و <code>body</code>، أما غير ذلك فلن يُسمح به وسيرفع اعتراض ‎<code>\Twig\Sandbox\SecurityError</code>. 
 
يكون كائن السياسة هو أول وسيط في منشئ صندوق الاختبار: <syntaxhighlight lang="php">
$sandbox = new \Twig\Extension\SandboxExtension($policy);
$twig->addExtension($sandbox);
</syntaxhighlight>ويكون وضع صندوق الاختبار معطلًا افتراضيًا ويجب أن يفعَّل عند إدخال شيفرة قوالب غير موثوق فيها باستخدام وسم <code>[[Twig/sandbox|sandbox]]</code>:<syntaxhighlight lang="twig">
{% sandbox %}
    {% include 'user.html' %}
{% endsandbox %}
</syntaxhighlight>تستطيع وضع جمبع القوالب في وضع صندوق الاختبار بتمرير <code>true</code> كوسيط ثاني لمنشئ التوسعة:<syntaxhighlight lang="twig">
$sandbox = new \Twig\Extension\SandboxExtension($policy, true);
</syntaxhighlight>
 
=== Profiler ===
تفعِّل توسعة <code>profiler</code> محللًا لقوالب Twig ويجب ألا يُستخدم إلا على الأجهزة التي تستخدمها للتطوير فقط إذ يضيف حملًا زائدًا:<syntaxhighlight lang="php">
$profile = new \Twig\Profiler\Profile();
$twig->addExtension(new \Twig\Extension\ProfilerExtension($profile));
 
$dumper = new \Twig\Profiler\Dumper\TextDumper();
echo $dumper->dump($profile
</syntaxhighlight>ويحتوي الملف profile على معلومات عن الوقت واستهلاك الذاكرة لتنفيذات القالب والكتلة والشيفرات الجامعة macro. كذلك تستطيع وضع البيانات في صيغة متوافقة مع [https://blackfire.io/ Blackfire.io]:<syntaxhighlight lang="php">
$dumper = new \Twig\Profiler\Dumper\BlackfireDumper();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
</syntaxhighlight>أنشئ [https://blackfire.io/signup?utm_source=twig&utm_medium=doc&utm_campaign=profiler حسابًا جديدًا مجانيًا] أولًا ثم ارفع الملف لجعله مرئيًا:<syntaxhighlight lang="php">
blackfire --slot=7 upload /path/to/profile.prof
</syntaxhighlight>
 
=== Optimizer ===
تحسِّن توسعة <code>optimizer</code> شجرة العقد قبل التصريف:<syntaxhighlight lang="php">
$twig->addExtension(new \Twig\Extension\OptimizerExtension());
</syntaxhighlight>وتكون جميع التحسينات مفعلة افتراضيًا، وتستطيع اختيار التحسينات التي تريد تفعيلها من خلال تمريرها إلى المنشئ:<syntaxhighlight lang="php">
$optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR);
 
$twig->addExtension($optimizer);
</syntaxhighlight>ويدعم Twig التحسينات التالية:<syntaxhighlight lang="php">
‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL
# ‫الذي يفعل جميع التحسينات، وهذا التحسين هو القيمة الافتراضية
 
‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE
# ‫يعطل جميع التحسينات، ويقلل ذلك من وقت التصريف لكن قد يزيد وقت التنفيذ والذاكرة المستهلكة.
 
‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR
# ‫يحسن وسم for من خلال حذف إنشاء متغير loop كلما أمكن ذلك
 
‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER
# ‫يحذف مرشح raw كلما أمكن
 
‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS
# ‫يبسط إنشاء المتغيرات والوصول إليها في القوالب المصرَّفة كلما أمكن
</syntaxhighlight>
== الاعتراضات Exceptions ==
يستطيع Twig أن يرفع الاعتراضات التالية:<syntaxhighlight lang="php">
‎\Twig\Error\Error
# ‫الاعتراض الأساسي لجميع الأخطاء
 
‎\Twig\Error\SyntaxError
# ‫يرفع ليخبر المستخدم أن ثمة مشكلة في بنية القالب اللغوية
 
‎\Twig\Error\RuntimeError
# يرفع عند حدوث خطأ أثناء وقت التشغيل، كما في حالة عدم وجود مرشح مثلً‫ا
 
‎\Twig\Error\LoaderError
# ‫يرفع عند حدوث خطأ أثناء تحميل القالب
 
‎\Twig\Sandbox\SecurityError
# ‫يرفع عند استدعاء وسم أو مرشح أو تابع في قالب صندوق الاختبار
</syntaxhighlight>
== انظر أيضًا ==
 
* [[Twig/advanced|توسيع Twig]]
* [[Twig/internals|المكونات الداخلية]]
* [[Twig/coding standards|معايير كتابة الشيفرة]]
 
== مصادر ==
 
* [https://twig.symfony.com/doc/3.x/api.html صفحة Twig للمطورين في توثيق Twig الرسمي]
 
[[تصنيف:Twig]]
[[تصنيف:Twig Intro]]

المراجعة الحالية بتاريخ 10:56، 7 أكتوبر 2022

تشرح هذه الصفحة واجهة برمجة التطبيقات API لمحرك القوالب Twig، وستكون مفيدة كمرجع لأولئك الذين يستخدمون واجهة القالب للتطبيق، فهي لا تشرح لغة القالب نفسه، وليست للذين ينشؤون قوالب Twig.

مقدمة

يستخدم Twig كائنًا مركزيًا يسمى البيئة -من الصنف ‎\Twig\Environment، وتُستخدم النُسخ instances التي لهذا الصنف في تخزين الإعدادات والتوسعات extensions وتحميل القوالب. وتنشئ أغلب التطبيقات كائن ‎\Twig\Environment واحد فقط أثناء تهيئة التطبيق app initialization وتستخدمه في تحميل القوالب، وقد يفيدنا أحيانًا أن يكون لدينا عدة بيئات جنبًا إلى جنب لها إعدادات مختلفة. تكون الطريقة المعتادة لإعداد Twig كي يحمِّل القوالب لتطبيق ما كما يلي غالبًا:

require_once '/path/to/vendor/autoload.php';

$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
$twig = new \Twig\Environment($loader, [
    'cache' => '/path/to/compilation_cache',
]);

ينشئ هذا بيئةَ قالب بالإعدادات الافتراضية، ومحمِّل يبحث عن القوالب في المجلد /path/to/templates/، وتوجد عدة محملات متاحة، كما تستطيع كتابة المحمل الخاص بك إذا أردت تحميل قوالب من قاعدة بيانات أو مصادر أخرى.

لاحظ أن الوسيط الثاني للبيئة ما هو إلا مصفوفة من الخيارات، فالخيار cache مثلًا هو مجلد لذاكرة التصريف compilation cache حيث يحتفظ Twig بالقوالب المصرَّفة لتجنب مرحلة التحليل parsing للطلبات التالية، ويختلف هذا كثيرًا عن الذاكرة المؤقتة التي تريد إضافتها للقوالب المقيَّمة، فلتلك يمكن استخدام أي مكتبة ذاكرة مؤقتة للغة PHP.

تصيير القوالب Rendering Templates

إذا أردت تحميل قالب من بيئة Twig فاستدع التابع load()‎ الذي يعيد نسخة من ‎\Twig\TemplateWrapper:

$template = $twig->load('index.html');

ولتصيير القالب مع بعض المتغيرات، استدع التابع render()‎:

echo $template->render(['the' => 'variables', 'go' => 'here']);

لاحظ أن التابع display()‎ ما هو إلا اختصار لكي نحصل على القالب المصيَّر rendered template. كذلك يمكنك تحميل القالب وتصييره في خطوة واحدة كما يلي:

echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']);

وإذا عرَّف القالب وحدات فيمكن تصييرها منفردة من خلال استدعاء renderBlock()‎:

echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);

خيارات البيئة

يمكن أن تمرر مصفوفة من الخيارات كوسيط ثاني للمنشئ constructor عند إنشاء نسخة جديدة من ‎\Twig\Environment:

$twig = new \Twig\Environment($loader, ['debug' => true]);

ويكون لدينا ما يلي من الخيارات المتاحة:

  • debug البولياني: حين يتحقق -أي يكون true- فإن القوالب المولَّدة يكون لها التابع ‎__toString()‎ الذي تستطيع استخدامه لعرض العقد المولَّدة، ويكون الافتراضي على false.
  • السلسلة النصية charset: يكون الافتراضي لها على utf-8، وتُستخدم مجموعة المحارف charset من قِبل القوالب.
  • السلسلة النصية cache أو false: مسار مطلق حيث تُخزَّن القوالب المصرَّفة، أو false لتعطيل التخزين المؤقت وهو الافتراضي.
  • الثنائي auto_reload: من المفيد عند استخدام Twig أن تعيد تصريف القالب كلما تغيرت الشيفرة المصدرية، وإذا لم توفر قيمة لخيار auto_reload فإنها ستُحدد تلقائيًا بناء على قيمة debug.
  • strict_variables البولياني: إذا كان false فسيتجاهل Twig المتغيرات غير الصالحة بصمت -وهي المتغيرات و/أو السمات/التوابع غير الموجودة-، ويستبدل قيمة غير معرفة null بها. أما حين يكون true فإن Twig يرفع اعتراضًا exception. وافتراضي هذا الخيار يكون false.
  • السلسلة النصية autoescape: يضع هذا الخيار خطة التهريب التلقائي الافتراضية name ، html ، js ، css ، url ، html_attr ، أو استدعاء PHP خلفي callback يأخذ "اسم الملف" للقالب ويعيد خطة التهريب لاستخدامها، ولا يمكن أن يكون الاستدعاء الخلفي اسم دالة لئلا يتعارض مع خطط التهريب المضمنة، فاضبط خطة التهريب إذًا لتكون false لتعطيل التهريب التلقائي. تحدد خطةُ التهريب name خطةَ التهريب التي يجب استخدامها لقالب مبني على توسعة اسم ملف القالب، ولا تتسبب هذه الخطة في أي حمل زائد overhead أثناء التشغيل لأن التهريب التلقائي يتم في وقت التصريف.
  • عدد التحسينات optimizations: راية توضح أي التحسينات التي يجب تطبيقها، ويكون الافتراضي لهذا الخيار هو ‎-1، حيث تكون جميع التحسينات مفعلة، وإذا أردت تعطيلها فاجعله على 0.

المحملات Loaders

تكون المحملات مسؤولة عن تحميل القوالب من مصادر مثل نظام الملفات.

ذاكرة التصريف المؤقتة Compilation Cache

تستطيع جميع محملات القوالب أن تخزن القوالب المصرَّفة في نظام الملفات من أجل الاستخدام المستقبلي، وهذا يسرع Twig كثيرًا بما أن القوالب تُصرَّف مرة واحدة فقط.

المحملات المضمنة Built-in Loaders

فيما يلي قائمة بالمحمٍّلات المضمنة في Twig:

\Twig\Loader\FilesystemLoader

يحمل القوالب من نظام التشغيل، ويستطيع العثور عليها إن كانت فيه، وهو الطريقة المفضلة لتحميلها:

$loader = new \Twig\Loader\FilesystemLoader($templateDir);

كما يبحث أيضًا في القوالب التي في مصفوفة من المجلدات:

$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);

وسيبحث Twig أولًا بهذه الإعدادات عن القوالب التي في ‎$templateDir1 وإذا لم تكن موجودة فسيرجع للبحث عنها في ‎$templateDir2. تستطيع إضافة المسارات أو إسباقها بشيء من خلال التابعيْن addPath()‎ و prependPath()‎:

$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);

كما يدعم محمل نظام الملفات القوالب ذات فضاءات الأسماء namespaced templates، وهذا يسمح لك بجمع قوالبك تحت فضاءات أسماء مختلفة يكون لها مسارات قوالب خاصة بها. إذا استخدمت التوابع setPath()‎ و addPAth()‎ و prependPath()‎ فحدد فضاء الاسم كوسيط ثاني، فإذا لم تحدد ذلك فإن هذه التوابع تتصرف على فضاء الاسم الرئيسي:

$loader->addPath($templateDir, 'admin');

يمكن الوصول إلى القوالب ذات فضاءات الأسماء من خلال الترميز الخاص ‎@namespace_name/template_path‎:

$twig->render('@admin/index.html', []);

يدعم ‎\Twig\Loader\FilesystemLoader المسارات المطلقة والنسبية، ويفضَّل استخدام المسارات النسبية لأنها تجعل مفاتيح الذاكرة المؤقتة cache keys مستقلة عن مجلد الجذر للمشروع، فهي تسمح مثلًا بتهيئة warming الذاكرة المؤقتة من خادم بناء حيث يكون المجلد مختلفًا عن المستخدم في خوادم العمل الحقيقية:

$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');

لاحظ أن Twig يستخدم getcwd()‎ للمسارات النسبية عند عدم تمرير المسار الجذر كوسيط ثاني.

\Twig\Loader\ArrayLoader

يحمِّل قالبًا من مصفوفة PHP، وتُمرَّر كمصفوفة سلاسل نصية مقيدة بأسماء القوالب:

$loader = new \Twig\Loader\ArrayLoader([
    'index.html' => 'Hello {{ name }}!',
]);
$twig = new \Twig\Environment($loader);

echo $twig->render('index.html', ['name' => 'Fabien']);

وهذا المحمِّل مفيد جدًا في اختبار الوحدات، كما يمكن استخدامه للمشاريع الصغيرة التي يكون من المنطقي فيها تخزين جميع القوالب في ملف PHP واحد.

وعند استخدام محمِّل Array مع آلية تخزين مؤقت فيجب أن تعلم أن مفتاح الذاكرة الجديد يولَّد في كل مرة يتغير فيها محتوى القالب، إذ أن مفتاح الذاكرة المؤقتة هو نفسه الشيفرة المصدرية للقالب، فإذا أردت الحفاظ على ذاكرتك المؤقتة من الخروج عن السيطرة فربما تود إخلاء الذاكرة القديمة بنفسك.

\Twig\Loader\ChainLoader

يفوِّض هذا المحمِّل مهمة تحميل القوالب إلى محمِّلات أخرى:

$loader1 = new \Twig\Loader\ArrayLoader([
    'base.html' => '{% block content %}{% endblock %}',
]);
$loader2 = new \Twig\Loader\ArrayLoader([
    'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
    'base.html'  => 'Will never be loaded',
]);

$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);

$twig = new \Twig\Environment($loader);

يحاول Twig مع كل محمِّل عند البحث عن قالب ما، ويعيد بمجرد العثور على قالب، وعند إخراج قالب index.html من المثال السابق فإن Twig سيحمله باستخدام ‎$loader2، على عكس قالب base.html الذي سيحمَّل من ‎$loader1.

لاحظ أنك تستطيع إضافة المحمِّلات باستخدام التابع addLocker()‎.

إنشاء المحمِّل الخاص بك

تستخدم جميع المحمِّلات ‎\Twig\Loader\LoaderInterface:

interface \Twig\Loader\LoaderInterface
{
    /**
     * تعيد السياق المصدري لاسم القالب المنطقي المعطى.
     *
     * @param string $name اسم القالب المنطقي
     *
     * @return \Twig\Source
     *
     * @throws \Twig\Error\LoaderError When $name is not found
     */
    public function getSourceContext($name);

    /**
     * تجلب مفتاح الذاكرة لاستخدامه للذاكرة المؤقتة لاسم قالب معطى.
     *
     * @param string $name اسم القالب الذي يجب تحميله.
     *
     * @return string مفتاح الذاكرة المؤقتة.
     *
     * @throws \Twig\Error\LoaderError When $name is not found
     */
    public function getCacheKey($name);

    /**
     * تتحقق إذا كان القالب ما زال جديدًا.
     *
     * @param string    $name اسم القالب.
     * @param timestamp $time آخر وقت تعديل للقالب المخزَّن.
     *
     * @return bool    تتحقق إذا كان القالب جديدًا فقط.
     *
     * @throws \Twig\Error\LoaderError When $name is not found
     */
    public function isFresh($name, $time);

    /**
     * تنظر إن كان لدينا الشيفرة المصدرية لقالب ما إذا كنا نعرف اسمه.
     *
     * @param string $name اسم القالب الذي نريد التحقق من إمكانية تحميله.
     *
     * @return bool    إذا كان هذا المحمِّل يعالج شيفرة هذا القالب المصدرية أم لا.
     */
    public function exists($name);
}

يجب أن يتحقق التابع isFresh()‎ -يعيد true- إذا أُعطي آخر وقت تعديل عليه مما إذا كان القالب المخزَّن جديدًا، وإلا فإنه يعيد false. كذلك، يجب أن يعيد التابع getSourceContext()‎ نسخة من ‎\Twig\source.

استخدام التوسعات Extensions

توسعات Twig هي حزم تضيف مزايا جديدة إليه، وتستطيع تسجيل توسعة من خلال التابع addExtension()‎:

$twig->addExtension(new \Twig\Extension\SandboxExtension());

وتأتي التوسعات التالية مع Twig:

  • TwigExtensionCoreExtension: تعرِّف جميع المزايا الأساسية لـ Twig.
  • TwigExtensionDebugExtension: تعرِّف دالة dump للمساعدة في تنقيح متغيرات القالب.
  • TwigExtensionEscaperExtension: تضيف تهريبًا تلقائيًا للخرج واحتمالية تهريب أو إلغاء تهريب كتل من الشيفرة.
  • TwigExtensionSandboxExtension: تضيف وضع صندوق الاختبار إلى بيئة Twig الافتراضية لتجعلها أكثر أمانًا لتقييم الشيفرات غير الموثوق فيها.
  • TwigExtensionProfilerExtension: تفعِّل المحلل profiler المضمن في Twig.
  • TwigExtensionOptimizerExtension: تحسِّن شجرة العُقد قبل التصريف.
  • TwigExtensionStringLoaderExtension: تعرِّف دالة template_from_string لتسمح بتحميل القوالب من سلسلة نصية في قالب ما.

وأما توسعات النواة Core و المهرِّب Escaper و المحسِّن Optimizer فتكون مسجلة افتراضيًا.

التوسعات المضمنة

يشرح هذا القسم المزايا المضافة بواسطة التوسعات المضمنة built-in extensions إلى Twig، ربما تود قراءة صفحة توسعة Twig لتعلم كيف تنشئ توسعاتك الخاصة بك.

Core

يعرِّف التوسعة أو الإضافة core جميع المزايا الأساسية في Twig:

Escaper

تضيف التوسعة escaper التهريب التلقائي للخرج إلى Twig، وتعرِّف وسمًا هو autoescape، ومرشحًا هو raw، وتستطيع تشغيل أو إيقاف خطة تهريب الخرج العامة عند إنشاء توسعة المهرِّب:

$escaper = new \Twig\Extension\EscaperExtension('html');
$twig->addExtension($escaper);

وتهرَّب جميع المتغيرات باستخدام خطة تهريب html إذا ضبط التوسعة على html، ما عدا التي تستخدم مرشح raw:

{{ article.to_html|raw }}

كما تستطيع تغيير وضع التهريب محليًا من خلال استخدام وسم autoescape:

{% autoescape 'html' %}
    {{ var }}
    {{ var|raw }}      {# var won't be escaped #}
    {{ var|escape }}   {# var won't be double-escaped #}
{% endautoescape %}

لكن انتبه إلى أن وسم autoescape ليس له تأثير على الملفات المضمنة. وتطبَّق قواعد التهريب كما يلي:

  • القيم مصنفة النوع Literals وهي الأعداد الصحيحة، القيم البوليانية، المصفوفات، ...إلخ المستخدمة في القالب مباشرة كمتغيرات أو وسائط لمرشحات لا تُهرَّب تلقائيًا أبدًا:
{{ "Twig<br/>" }} {# لن تهرَّب #}

{% set text = "Twig<br/>" %}
{{ text }} {# ستهرَّب #}
  • التعابير التي تكون نتيجتها قيمة مصنفة النوع أو متغير آمن لا تهرَّب تلقائيًا كذلك:
{{ foo ? "Twig<br/>" : "<br/>Twig" }} {# لن تهرَّب #}

{% set text = "Twig<br/>" %}
{{ true ? text : "<br/>Twig" }} {# تهرَّب #}
{{ false ? text : "<br/>Twig" }} {# لن تهرَّب #}

{% set text = "Twig<br/>" %}
{{ foo ? text|raw : "<br/>Twig" }} {# لن تهرَّب #}
  • تحوَّل الكائنات التي بها التابع ‎_tostring إلى سلاسل نصية وتهرَّب، ويمكنك تحديد بعض الأصناف أو/و الواجهات لتكون آمنة لبعض الخطط من خلال EscaperExtension::addSafeClass()‎ كما يلي:
// HTML ليكون آمنًا لخطة Foo حدد كائن صنف
$escaper->addSafeClass('Foo', ['html']);

// HTML ليكون آمنًا لخطة Foo حدد كائن واجهة
$escaper->addSafeClass('FooInterface', ['html']);

// JS و HTML ليكون آمنًا لخطتي Foo حدد كائن صنف
$escaper->addSafeClass('Foo', ['html', 'js']);

// ليكون آمنًا لجميع الخطط Foo حدد كائن صنف
$escaper->addSafeClass('Foo', ['all']);
  • يطبَّق التهريب قبل الطباعة وبعد تطبيق جميع المرشحات الأخرى:
{{ var|upper }} {# {{ var|upper|escape }} مكافئ لـ #}
  • يجب أن يُستخدم مرشح raw في نهاية سلسلة المرشحات فقط:
{{ var|raw|upper }} {# سيهرَّب #}

{{ var|upper|raw }} {# لن يهرَّب #}

لا يطبَّق التهريب التلقائي إذا كان المرشح الأخير في السلسلة محددًا على أنه آمن للسياق الحالي -html مثلًا أو JS-، فمثلًا يكون كل من escape و escape('html') آمنين لـ html، ويكون escape('js') آمنًا لجافاسكربت، ويكون raw آمنًا لأي شيء.

{% autoescape 'js' %}
    {{ var|escape('html') }} {# will be escaped for HTML and JavaScript #}
    {{ var }} {# will be escaped for JavaScript #}
    {{ var|escape('js') }} {# won't be double-escaped #}
{% endautoescape %}
  • لاحظ أن التهريب التلقائي به بعض القيود بما أن التهريب يطبق على التعابير بعد تقييمها، فمثلًا لن يعطيك {{ foo|raw ~ bar }} النتيجة التي تريدها عند العمل مع ضم ما concatenation إذ أن التهريب يطبق على نتيجة الضم وليس على المتغيرات منفردة، وعليه لن يكون لمرشح raw أي تأثير هنا.

Sandbox

يمكن استخدام توسعة صندوق الاختبار sandbox لتقييم الشيفرات غير الموثوق فيها إذ يُمنع الوصول إلى السمات والتوابع غير الآمنة، ويدار نظام الأمان في صندوق الاختبار من خلال نسخة سياسة policy instance، ويأتي Twig افتراضيًا بصنف سياسة واحد هو ‎\Twig\Sandbox\SecurityPolicyK، ويسمح لك هذا الصنف بوضع بعض الوسوم والمرشحات والخصائص والتوابع في القائمة البيضاء المسموح بها:

$tags = ['if'];
$filters = ['upper'];
$methods = [
    'Article' => ['getTitle', 'getBody'],
];
$properties = [
    'Article' => ['title', 'body'],
];
$functions = ['range'];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);

ووفقًا للإعدادات السابقة فإن سياسة الأمان ستسمح باستخدام وسم if ومرشح upper فقط، كما لن يسمح للقوالب أن تستدعي إلا التابعين getTitle()‎ و getBody()‎ على كائنات Article، وكذلك الخاصيتين title و body، أما غير ذلك فلن يُسمح به وسيرفع اعتراض ‎\Twig\Sandbox\SecurityError. يكون كائن السياسة هو أول وسيط في منشئ صندوق الاختبار:

$sandbox = new \Twig\Extension\SandboxExtension($policy);
$twig->addExtension($sandbox);

ويكون وضع صندوق الاختبار معطلًا افتراضيًا ويجب أن يفعَّل عند إدخال شيفرة قوالب غير موثوق فيها باستخدام وسم sandbox:

{% sandbox %}
    {% include 'user.html' %}
{% endsandbox %}

تستطيع وضع جمبع القوالب في وضع صندوق الاختبار بتمرير true كوسيط ثاني لمنشئ التوسعة:

$sandbox = new \Twig\Extension\SandboxExtension($policy, true);

Profiler

تفعِّل توسعة profiler محللًا لقوالب Twig ويجب ألا يُستخدم إلا على الأجهزة التي تستخدمها للتطوير فقط إذ يضيف حملًا زائدًا:

$profile = new \Twig\Profiler\Profile();
$twig->addExtension(new \Twig\Extension\ProfilerExtension($profile));

$dumper = new \Twig\Profiler\Dumper\TextDumper();
echo $dumper->dump($profile

ويحتوي الملف profile على معلومات عن الوقت واستهلاك الذاكرة لتنفيذات القالب والكتلة والشيفرات الجامعة macro. كذلك تستطيع وضع البيانات في صيغة متوافقة مع Blackfire.io:

$dumper = new \Twig\Profiler\Dumper\BlackfireDumper();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));

أنشئ حسابًا جديدًا مجانيًا أولًا ثم ارفع الملف لجعله مرئيًا:

blackfire --slot=7 upload /path/to/profile.prof

Optimizer

تحسِّن توسعة optimizer شجرة العقد قبل التصريف:

$twig->addExtension(new \Twig\Extension\OptimizerExtension());

وتكون جميع التحسينات مفعلة افتراضيًا، وتستطيع اختيار التحسينات التي تريد تفعيلها من خلال تمريرها إلى المنشئ:

$optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR);

$twig->addExtension($optimizer);

ويدعم Twig التحسينات التالية:

‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL
# ‫الذي يفعل جميع التحسينات، وهذا التحسين هو القيمة الافتراضية

‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE
# ‫يعطل جميع التحسينات، ويقلل ذلك من وقت التصريف لكن قد يزيد وقت التنفيذ والذاكرة المستهلكة.

‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR
# ‫يحسن وسم for من خلال حذف إنشاء متغير loop كلما أمكن ذلك

‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER
# ‫يحذف مرشح raw كلما أمكن

‎\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS
# ‫يبسط إنشاء المتغيرات والوصول إليها في القوالب المصرَّفة كلما أمكن

الاعتراضات Exceptions

يستطيع Twig أن يرفع الاعتراضات التالية:

‎\Twig\Error\Error
# ‫الاعتراض الأساسي لجميع الأخطاء

‎\Twig\Error\SyntaxError
# ‫يرفع ليخبر المستخدم أن ثمة مشكلة في بنية القالب اللغوية

‎\Twig\Error\RuntimeError
# يرفع عند حدوث خطأ أثناء وقت التشغيل، كما في حالة عدم وجود مرشح مثلً‫ا

‎\Twig\Error\LoaderError
# ‫يرفع عند حدوث خطأ أثناء تحميل القالب

‎\Twig\Sandbox\SecurityError
# ‫يرفع عند استدعاء وسم أو مرشح أو تابع في قالب صندوق الاختبار

انظر أيضًا

مصادر