Twig للمطورين
هذه الصفحة تشرح واجهة برمجة التطبيقات (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 خلفي يأخذ "اسم الملف" للقالب ويعيد خطة التهريب لاستخدامها، ولا يمكن أن يكون الاستدعاء الخلفي اسم دالة لئلا يتعارض مع خطط التهريب المضمنة). فاضبط خطة التهريب إذًا لتكون false لتعطيل التهريب التلقائي. تحدد خطةُ التهريب name خطةَ التهريب التي يجب استخدامها لقالب مبني على توسيع اسم ملف القالب، ولا تتسبب هذه الخطة في أي حمل زائد (overhead) أثناء التشغيل لأن التهريب التلقائي يتم في وقت التصريف.
- العدد optimizations: راية توضح أي التحسينات التي يجب تطبيقها، ويكون الافتراضي لهذا الخيار هو -1، حيث تكون جميع التحسينات مفعلة، وإذا أردت تعطيلها فاجعله على 0.
المحملات (Loaders)
تكون المحملات مسؤولة عن تحميل القوالب من مصادر مثل نظام الملفات.
ذاكرة التصريف المؤقتة (Compilation Cache)
تستطيع جميع محملات القوالب أن تخزن القوالب المصرَّفة في نظام الملفات من أجل الاستخدام المستقبلي، وهذا يسرع Twig كثيرًا بما أن القوالب تُصرَّف مرة واحدة فقط.
المحملات المضمنة (Built-in Loaders)
فيما يلي قائمة بالمحمٍّلات المضمنة في Twig:
\Twig\Loader\FilesystemLoader
يحمل \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);
كما يدعم محمل نظام الملفات القوالب ذات فضاءات الأسماء، وهذا يسمح لك بجمع قوالبك تحت فضاءات أسماء مختلفة يكون لها مسارات قوالب خاصة بها. إذا استخدمت التوابع 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
يحمِّل \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
يفوِّض \Twig\Loader\ChainLoader مهمة تحميل القوالب إلى محمِّلات أخرى:
1
2
3
4
5
6
7
8
9
10
11
$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:
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
{
/**
* تعيد السياق المصدري لاسم القالب المنطقي المعطى.
*
* @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: