الفرق بين المراجعتين لصفحة: «Laravel/facades»
تسنيم-ولهازي (نقاش | مساهمات) لا ملخص تعديل |
رؤيا-بنعطية (نقاش | مساهمات) ط استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}' |
||
(8 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:الواجهات الساكنة (Facades)في Laravel}}</noinclude> | <noinclude>{{DISPLAYTITLE:الواجهات الساكنة (Facades) في Laravel}}</noinclude> | ||
== مقدمة == | == مقدمة == | ||
تُوفِّر الواجهات الساكنة واجهة "ساكنة" (static) للأصناف المتوافرة في حاوي خدمات تطبيقك. يأتي Laravel مع عدة واجهات تمكنك من استخدام كل خاصيات Laravel تقريبًا. تمثل واجهات Laravel الساكنة "وسطاء ساكنات" (static proxies) للأصناف الأساسية بحاوي الخدمات مما يوفر كل فوائد الصِّيغ (syntax) المقتضبة والمُعبِّرة مع الحفاظ على قابلية الاختبار ومرونة أكبر من الدالات الساكنة التقليدية. | تُوفِّر الواجهات الساكنة واجهة "ساكنة" (static) للأصناف المتوافرة في حاوي خدمات تطبيقك. يأتي [[Laravel]] مع عدة واجهات تمكنك من استخدام كل خاصيات [[Laravel]] تقريبًا. تمثل واجهات Laravel الساكنة "وسطاء ساكنات" (static proxies) للأصناف الأساسية بحاوي الخدمات مما يوفر كل فوائد الصِّيغ (syntax) المقتضبة والمُعبِّرة مع الحفاظ على قابلية الاختبار ومرونة أكبر من الدالات الساكنة التقليدية. | ||
كل واجهات Laravel الساكنة مُعرَّفةٌ في مجال الأسماء <code>Illuminate\Support\Facades</code>. يمكننا الوصول لواجهة ساكنة بهذه الطريقة:<syntaxhighlight lang="php"> | كل واجهات [[Laravel]] الساكنة مُعرَّفةٌ في مجال الأسماء <code>Illuminate\Support\Facades</code>. يمكننا الوصول لواجهة ساكنة بهذه الطريقة:<syntaxhighlight lang="php"> | ||
use Illuminate\Support\Facades\Cache; | use Illuminate\Support\Facades\Cache; | ||
سطر 8: | سطر 8: | ||
return Cache::get('key'); | return Cache::get('key'); | ||
}); | }); | ||
</syntaxhighlight>سنستخدم في كثير من الأمثلة الواجهات الساكنة لعرض عدة خاصيات لإطار العمل في توثيق Laravel. | </syntaxhighlight>سنستخدم في كثير من الأمثلة الواجهات الساكنة لعرض عدة خاصيات لإطار العمل في توثيق [[Laravel]]. | ||
== متى نستخدم الواجهات الساكنة؟ == | == متى نستخدم الواجهات الساكنة؟ == | ||
للواجهات الساكنة فوائد كثيرة فهي توفِّر صيغةً مقتضبةً وسهلة التذكّر تسمح لنا باستخدام خاصيات Laravel دون حفظ أسماء الأصناف الطويلة التي تسلتزم إضافتها وإعدادها يدويًا. علاوة على ذلك، اختبارهن أسهل بفضل استخدامهن الفريد لدوال PHP الدَيناميكيَة. | للواجهات الساكنة فوائد كثيرة فهي توفِّر صيغةً مقتضبةً وسهلة التذكّر تسمح لنا باستخدام خاصيات [[Laravel]] دون حفظ أسماء الأصناف الطويلة التي تسلتزم إضافتها وإعدادها يدويًا. علاوة على ذلك، اختبارهن أسهل بفضل استخدامهن الفريد لدوال PHP الدَيناميكيَة. | ||
يجب الاحتياط عند استخدام الواجهات الساكنة حيث أنّ خطرهم الرئيسي هو زحف مجال الصَنف (class scope). بما أن الواجهات السَاكنة سهلة الاستخدام ولا تتطلب إضافات، قد يسهل ترك صنفك يواصل التضخَم بشكل هام عند استخدام عدَة واجهات سَاكنة في صنف واحد. يمكن الحد من هذه المشكلة باستخدام إضافة الاعتماديات (dependency injection)، اذ ان التحذيرات المرئية التي تصدرها دالة بناء constructor ضخمة تعلمك ان صنفك تضخَّم أكثر من اللازم. لذلك أعر انتباهًا خاصًا لحجم صنفك كي يظل مجال مسؤوليته (scope of responsibility) ضيَقًا. | يجب الاحتياط عند استخدام الواجهات الساكنة حيث أنّ خطرهم الرئيسي هو زحف مجال الصَنف (class scope). بما أن الواجهات السَاكنة سهلة الاستخدام ولا تتطلب إضافات، قد يسهل ترك صنفك يواصل التضخَم بشكل هام عند استخدام عدَة واجهات سَاكنة في صنف واحد. يمكن الحد من هذه المشكلة باستخدام إضافة الاعتماديات (dependency injection)، اذ ان التحذيرات المرئية التي تصدرها دالة بناء constructor ضخمة تعلمك ان صنفك تضخَّم أكثر من اللازم. لذلك أعر انتباهًا خاصًا لحجم صنفك كي يظل مجال مسؤوليته (scope of responsibility) ضيَقًا. | ||
''' | '''ملاحظة''': عند بناء حزمة طرف ثالث تتعامل مع Laravel، من الأفضل إضافة [[Laravel/contracts|عقود Laravel]] (Laravel contracts) بدل استخدام الواجهات الساكنة لأنّ الحزم المبنيّة خارج [[Laravel]] ذاته لن تستطيع استخدام مساعدي اختبار واجهات Laravel الساكنة (facade testing helpers) | ||
=== الواجهات وإضافة الاعتماديّة (dependency injection) === | === الواجهات وإضافة الاعتماديّة (dependency injection) === | ||
سطر 47: | سطر 47: | ||
=== الواجهات الساكنات والدوال البانية المساعدة (Helper Function) === | === الواجهات الساكنات والدوال البانية المساعدة (Helper Function) === | ||
إضافة للواجهات الساكنة، يتضمن Laravel عدة دوال بانية "مُساعدة" قادرة على تنفيذ مهام شائعة مثل توليد | إضافة للواجهات الساكنة، يتضمن [[Laravel]] عدة دوال بانية "مُساعدة" قادرة على تنفيذ مهام شائعة مثل توليد الواجهات (views)، وإطلاق الأحداث، وإرسال الأعمال (jobs)، أو إرسال ردود HTTP. تقوم عدَة دوال مُساعدة بنفس وظيفة الواجهة السَاكنة المناظرة. ففي المثال الآتي سيكون استدعاء هذه الواجهة هو نظير استدعاء الدالة المساعدة:<syntaxhighlight lang="php"> | ||
return View::make('profile'); | return View::make('profile'); | ||
سطر 55: | سطر 55: | ||
return cache('key'); | return cache('key'); | ||
}); | }); | ||
</syntaxhighlight>مُساعد الذاكرة المؤقتة سيستدعي | </syntaxhighlight>مُساعد الذاكرة المؤقتة سيستدعي التابع <code>get</code> على الصَنف الكامن وراء واجهة الذاكرة المؤقتة الساكنة وراء الكواليس. لذا نستطيع كتابة الاختبار التالي للتحقق من أن التابع استُدعِيَ بنفس المتغيَر الوسيط (argument) الذي نتوقَعه رغم أننا نستخدم الداَلة المساعدة:<syntaxhighlight lang="php"> | ||
use Illuminate\Support\Facades\Cache; | use Illuminate\Support\Facades\Cache; | ||
سطر 75: | سطر 75: | ||
== كيفية عمل الواجهات الساكنة == | == كيفية عمل الواجهات الساكنة == | ||
في تطبيقات | في تطبيقات [[Laravel]]، الواجهة الساكنة هي صنف يوفر الوصول لكائن من الحاوي. الآلية التي تسمح بحدوث هذا موجودة في الصنف <code>Facade</code>. واجهات [[Laravel]] الساكنة إضافة لأي واجهة تنشئها ستوسِّع صنف <code>Illuminate\Support\Facades\Facade</code> الأساسي. | ||
يستغل صنف الواجهة الساكنة <code>Facade</code> الأساسي الدالة السحرية <code>()callStatic__</code> لتأجيل الاستدعاء من الواجهة لكائن مُسْتَبْيَن من الحاوي. في المثال أدناه يُرسَل استدعاء نظام لذاكرة Laravel المؤقتة. بنظرة خاطفة على هذه التعليمات يمكن للمرء افتراض أن الدالة الساكنة <code>get</code> استُدعِيَت على صنف ذاكرة التخزين المؤقتة <code>Cache</code>:<syntaxhighlight lang="php"> | يستغل صنف الواجهة الساكنة <code>Facade</code> الأساسي الدالة السحرية <code>()callStatic__</code> لتأجيل الاستدعاء من الواجهة لكائن مُسْتَبْيَن من الحاوي. في المثال أدناه يُرسَل استدعاء نظام لذاكرة [[Laravel]] المؤقتة. بنظرة خاطفة على هذه التعليمات يمكن للمرء افتراض أن الدالة الساكنة <code>get</code> استُدعِيَت على صنف ذاكرة التخزين المؤقتة <code>Cache</code>:<syntaxhighlight lang="php"> | ||
<?php | <?php | ||
سطر 101: | سطر 101: | ||
} | } | ||
</syntaxhighlight>لاحظ كيف أننا "نستورد" واجهة ذاكرة التخزين المؤقتة <code>Cache</code> قرب الجزء العلوي من الملف. هذه الواجهة بمثابة وكيل للوصول لتعريف الاستخدام (implementation) الكامن وراء واجهة <code>Illuminate\Contracts\Cache\Factory</code>. سيمرر أي استدعاء نقوم به باستخدام الواجهة الساكنة للنسخة الكامنة وراء خدمة ذاكرة Laravel المؤقتة. | </syntaxhighlight>لاحظ كيف أننا "نستورد" واجهة ذاكرة التخزين المؤقتة <code>Cache</code> قرب الجزء العلوي من الملف. هذه الواجهة بمثابة وكيل للوصول لتعريف الاستخدام (implementation) الكامن وراء واجهة <code>Illuminate\Contracts\Cache\Factory</code>. سيمرر أي استدعاء نقوم به باستخدام الواجهة الساكنة للنسخة الكامنة وراء خدمة ذاكرة [[Laravel]] المؤقتة. | ||
إن نظرنا لصنف <code>Illuminate\Support\Facades\Cache</code>، سنرى أنه لا وجود | إن نظرنا لصنف <code>Illuminate\Support\Facades\Cache</code>، سنرى أنه لا وجود للتابع الساكن <code>get</code>:<syntaxhighlight lang="php"> | ||
class Cache extends Facade | class Cache extends Facade | ||
{ | { | ||
سطر 113: | سطر 113: | ||
protected static function getFacadeAccessor() { return 'cache'; } | protected static function getFacadeAccessor() { return 'cache'; } | ||
} | } | ||
</syntaxhighlight>بدلًا عن هذا، تُوسِّع واجهة ذاكرة التخزين المؤقتة الساكنة <code>Cache</code> صنف الواجهة الساكنة الأساسي <code>Facade</code> وتُعرًف | </syntaxhighlight>بدلًا عن هذا، تُوسِّع واجهة ذاكرة التخزين المؤقتة الساكنة <code>Cache</code> صنف الواجهة الساكنة الأساسي <code>Facade</code> وتُعرًف التابع <code>()getFacadeAccessor</code>. وظيفة هذا التابع هي رد اسم ارتباط حاوي الخدمات. يستبين [[Laravel]] ارتباط الذاكرة المؤقتة <code>cache</code> من حاوي الخدمات عندما يشير المستخدم لأي دالة ساكنة بواجهة ذاكرة التخزين المؤقتة الساكنة، ثم يُنفِّذ الدالة المطلوبة (في هذه الحالة <code>get</code>) على ذاك الكائن. | ||
== الواجهات الساكنة في الوقت الحالي (Real-Time Facades) == | == الواجهات الساكنة في الوقت الحالي (Real-Time Facades) == | ||
يمكنك معالجة أي صنف في تطبيقك كما لو كان واجهة ساكنة باستخدام الواجهات الساكنة في الوقت الحالي. لتوضيح كيفية الاستخدام فلندرس بديلا. فلنفترض مثلًا أن لنَموذَجِنَا <code>Podcast</code> | يمكنك معالجة أي صنف في تطبيقك كما لو كان واجهة ساكنة باستخدام الواجهات الساكنة في الوقت الحالي. لتوضيح كيفية الاستخدام فلندرس بديلا. فلنفترض مثلًا أن لنَموذَجِنَا <code>Podcast</code> التابع <code>publish</code>. لكي ننشر podcast نحتاج لإضافة نسخة <code>Publisher</code> :<syntaxhighlight lang="php"> | ||
<?php | <?php | ||
سطر 140: | سطر 140: | ||
} | } | ||
</syntaxhighlight>تسمح لنا إضافة تعريف استخدام للناشر | </syntaxhighlight>تسمح لنا إضافة تعريف استخدام للناشر للتابع باختبار الدالة بسهولة على انفراد بما أننا قادرون على تقليد (mock) الناشر المُضَاف. مع ذلك يستلزمنا أن نُمَرِّر نسخة من publisher في كل مرة نستدعي فيها التابع <code>publish</code>. يمكننا الحفاظ على نفس القدرة على الاختبار دون الاضطرار إلى تمرير نسخة <code>Publisher</code> صراحة (explicitly) باستخدام الواجهات الساكنة بالوقت الحالي. | ||
لتوليد واجهات ساكنة بالوقت الحالي، أسبق مجال أسماء الصنف المُستَوْرَد بالكلمة <code>Facades</code>:<syntaxhighlight lang="php"> | لتوليد واجهات ساكنة بالوقت الحالي، أسبق مجال أسماء الصنف المُستَوْرَد بالكلمة <code>Facades</code>:<syntaxhighlight lang="php"> | ||
سطر 165: | سطر 165: | ||
} | } | ||
</syntaxhighlight>يستبين تعريف استخدام الناشر من حاوي الخدمات باستخدام جزء الواجهة (interface) أو اسم الصنف الذي يظهر بعد استخدام واجهات ساكنة بالوقت الحالي بعد سابقة <code>Facades</code>. يمكننا استخدام مُساعدي اختبار Laravel المُدمجات لتقليد استدعاء | </syntaxhighlight>يستبين تعريف استخدام الناشر من حاوي الخدمات باستخدام جزء الواجهة (interface) أو اسم الصنف الذي يظهر بعد استخدام واجهات ساكنة بالوقت الحالي بعد سابقة <code>Facades</code>. يمكننا استخدام مُساعدي اختبار [[Laravel]] المُدمجات لتقليد استدعاء هذا التابع عند الاختبار:<syntaxhighlight lang="php"> | ||
<?php | <?php | ||
سطر 198: | سطر 198: | ||
== مرجع صنف الواجهات الساكنة == | == مرجع صنف الواجهات الساكنة == | ||
{| class="wikitable" | {| class="wikitable" | ||
! | |||
== الواجهة الساكنة (Facade) == | == الواجهة الساكنة (Facade) == | ||
! | |||
== الصنف == | == الصنف == | ||
! | |||
== ارتباط حاوي الخدمات == | == ارتباط حاوي الخدمات == | ||
|- | |- | ||
|App | |App | ||
|Illuminate\Foundation\Application | |<code>Illuminate\Foundation\Application</code> | ||
|app | |app | ||
|- | |- | ||
|Artisan | |Artisan | ||
|Illuminate\Contracts\Console\Kernel | |<code>Illuminate\Contracts\Console\Kernel</code> | ||
|artisan | |artisan | ||
|- | |- | ||
|Auth | |Auth | ||
|Illuminate\Auth\AuthManager | |<code>Illuminate\Auth\AuthManager</code> | ||
|auth | |auth | ||
|- | |- | ||
|Auth (Instance | |(Auth (Instance | ||
|Illuminate\Contracts\Auth\Guard | |<code>Illuminate\Contracts\Auth\Guard</code> | ||
|auth.driver | |auth.driver | ||
|- | |- | ||
|Blade | |Blade | ||
|Illuminate\View\Compilers\BladeCompiler | |<code>Illuminate\View\Compilers\BladeCompiler</code> | ||
|blade.compiler | |blade.compiler | ||
|- | |- | ||
|Broadcast | |Broadcast | ||
|Illuminate\Contracts\Broadcasting\Factory | |<code>Illuminate\Contracts\Broadcasting\Factory</code> | ||
| | | | ||
|- | |- | ||
|Broadcast (Instance | |(Broadcast (Instance | ||
|Illuminate\Contracts\Broadcasting\Broadcaster | |<code>Illuminate\Contracts\Broadcasting\Broadcaster</code> | ||
| | | | ||
|- | |- | ||
|Bus | |Bus | ||
|Illuminate\Contracts\Bus\Dispatcher | |<code>Illuminate\Contracts\Bus\Dispatcher</code> | ||
| | | | ||
|- | |- | ||
|Cache | |Cache | ||
|Illuminate\Cache\CacheManager | |<code>Illuminate\Cache\CacheManager</code> | ||
|cache | |cache | ||
|- | |- | ||
|Cache (Instance | |(Cache (Instance | ||
|Illuminate\Cache\Repository | |<code>Illuminate\Cache\Repository</code> | ||
|cache.store | |cache.store | ||
|- | |- | ||
|Config | |Config | ||
|Illuminate\Config\Repository | |<code>Illuminate\Config\Repository</code> | ||
|config | |config | ||
|- | |- | ||
|Cookie | |Cookie | ||
|Illuminate\Cookie\CookieJar | |<code>Illuminate\Cookie\CookieJar</code> | ||
|cookie | |cookie | ||
|- | |- | ||
|Crypt | |Crypt | ||
|Illuminate\Encryption\Encrypter | |<code>Illuminate\Encryption\Encrypter</code> | ||
|encrypter | |encrypter | ||
|- | |- | ||
|DB | |DB | ||
|Illuminate\Database\DatabaseManager | |<code>Illuminate\Database\DatabaseManager</code> | ||
|db | |db | ||
|- | |- | ||
|DB (Instance | |(DB (Instance | ||
|Illuminate\Database\Connection | |<code>Illuminate\Database\Connection</code> | ||
|db.connection | |db.connection | ||
|- | |- | ||
|Event | |Event | ||
|Illuminate\Events\Dispatcher | |<code>Illuminate\Events\Dispatcher</code> | ||
|events | |events | ||
|- | |- | ||
|File | |File | ||
|Illuminate\Filesystem\Filesystem | |<code>Illuminate\Filesystem\Filesystem</code> | ||
|files | |files | ||
|- | |- | ||
|Gate | |Gate | ||
|Illuminate\Contracts\Auth\Access\Gate | |<code>Illuminate\Contracts\Auth\Access\Gate</code> | ||
| | | | ||
|- | |- | ||
|Hash | |Hash | ||
|Illuminate\Contracts\Hashing\Hasher | |<code>Illuminate\Contracts\Hashing\Hasher</code> | ||
|hash | |hash | ||
|- | |- | ||
|Lang | |Lang | ||
|Illuminate\Translation\Translator | |<code>Illuminate\Translation\Translator</code> | ||
|translator | |translator | ||
|- | |- | ||
|Log | |Log | ||
|Illuminate\Log\Logger | |<code>Illuminate\Log\Logger</code> | ||
|log | |log | ||
|- | |- | ||
|Mail | |Mail | ||
|Illuminate\Mail\Mailer | |<code>Illuminate\Mail\Mailer</code> | ||
|mailer | |mailer | ||
|- | |- | ||
|Notification | |Notification | ||
|Illuminate\Notifications\ChannelManager | |<code>Illuminate\Notifications\ChannelManager</code> | ||
| | | | ||
|- | |- | ||
|Password | |Password | ||
|Illuminate\Auth\Passwords\PasswordBrokerManager | |<code>Illuminate\Auth\Passwords\PasswordBrokerManager</code> | ||
|auth.password | |auth.password | ||
|- | |- | ||
|Password (Instance | |(Password (Instance | ||
|Illuminate\Auth\Passwords\PasswordBroker | |<code>Illuminate\Auth\Passwords\PasswordBroker</code> | ||
|auth.password.broker | |auth.password.broker | ||
|- | |- | ||
|Queue | |Queue | ||
|Illuminate\Queue\QueueManager | |<code>Illuminate\Queue\QueueManager</code> | ||
|queue | |queue | ||
|- | |- | ||
|Queue (Instance | |(Queue (Instance | ||
|Illuminate\Contracts\Queue\Queue | |<code>Illuminate\Contracts\Queue\Queue</code> | ||
|queue.connection | |queue.connection | ||
|- | |- | ||
|Queue (Base Class | |(Queue (Base Class | ||
|Illuminate\Queue\Queue | |<code>Illuminate\Queue\Queue</code> | ||
| | | | ||
|- | |- | ||
|Redirect | |Redirect | ||
|Illuminate\Routing\Redirector | |<code>Illuminate\Routing\Redirector</code> | ||
|redirect | |redirect | ||
|- | |- | ||
|Redis | |Redis | ||
|Illuminate\Redis\RedisManager | |<code>Illuminate\Redis\RedisManager</code> | ||
|redis | |redis | ||
|- | |- | ||
|Redis (Instance | |(Redis (Instance | ||
|Illuminate\Redis\Connections\Connection | |<code>Illuminate\Redis\Connections\Connection</code> | ||
|redis.connection | |redis.connection | ||
|- | |- | ||
|Request | |Request | ||
|Illuminate\Http\Request | |<code>Illuminate\Http\Request</code> | ||
|request | |request | ||
|- | |- | ||
|Response | |Response | ||
|Illuminate\Contracts\Routing\ResponseFactory | |<code>Illuminate\Contracts\Routing\ResponseFactory</code> | ||
| | | | ||
|- | |- | ||
|Response (Instance | |(Response (Instance | ||
|Illuminate\Http\Response | |<code>Illuminate\Http\Response</code> | ||
| | | | ||
|- | |- | ||
|Route | |Route | ||
|Illuminate\Routing\Router | |<code>Illuminate\Routing\Router</code> | ||
|router | |router | ||
|- | |- | ||
|Schema | |Schema | ||
|Illuminate\Database\Schema\Builder | |<code>Illuminate\Database\Schema\Builder</code> | ||
| | | | ||
|- | |- | ||
|Session | |Session | ||
|Illuminate\Session\SessionManager | |<code>Illuminate\Session\SessionManager</code> | ||
|session | |session | ||
|- | |- | ||
|Session (Instance | |(Session (Instance | ||
|Illuminate\Session\Store | |<code>Illuminate\Session\Store</code> | ||
|session.store | |session.store | ||
|- | |- | ||
|Storage | |Storage | ||
|Illuminate\Filesystem\FilesystemManager | |<code>Illuminate\Filesystem\FilesystemManager</code> | ||
|filesystem | |filesystem | ||
|- | |- | ||
|Storage (Instance | |(Storage (Instance | ||
|Illuminate\Contracts\Filesystem\Filesystem | |<code>Illuminate\Contracts\Filesystem\Filesystem</code> | ||
|filesystem.disk | |filesystem.disk | ||
|- | |- | ||
|URL | |URL | ||
|Illuminate\Routing\UrlGenerator | |<code>Illuminate\Routing\UrlGenerator</code> | ||
|url | |url | ||
|- | |- | ||
|Validator | |Validator | ||
|Illuminate\Validation\Factory | |<code>Illuminate\Validation\Factory</code> | ||
|validator | |validator | ||
|- | |- | ||
|Validator (Instance | |(Validator (Instance | ||
|Illuminate\Validation\Validator | |<code>Illuminate\Validation\Validator</code> | ||
| | | | ||
|- | |- | ||
|View | |View | ||
|Illuminate\View\Factory | |<code>Illuminate\View\Factory</code> | ||
|view | |view | ||
|- | |- | ||
|View (Instance | |(View (Instance | ||
|Illuminate\View\View | |<code>Illuminate\View\View</code> | ||
| | | | ||
|} | |} | ||
== مصادر == | |||
* [https://laravel.com/docs/5.6/facades صفحة Facades في توثيق Laravel الرسمي.] | |||
[[تصنيف:Laravel|{{SUBPAGENAME}}]] | |||
[[تصنيف:Laravel Architecture Concepts|{{SUBPAGENAME}}]] |
المراجعة الحالية بتاريخ 13:23، 23 أكتوبر 2018
مقدمة
تُوفِّر الواجهات الساكنة واجهة "ساكنة" (static) للأصناف المتوافرة في حاوي خدمات تطبيقك. يأتي Laravel مع عدة واجهات تمكنك من استخدام كل خاصيات Laravel تقريبًا. تمثل واجهات Laravel الساكنة "وسطاء ساكنات" (static proxies) للأصناف الأساسية بحاوي الخدمات مما يوفر كل فوائد الصِّيغ (syntax) المقتضبة والمُعبِّرة مع الحفاظ على قابلية الاختبار ومرونة أكبر من الدالات الساكنة التقليدية.
كل واجهات Laravel الساكنة مُعرَّفةٌ في مجال الأسماء Illuminate\Support\Facades
. يمكننا الوصول لواجهة ساكنة بهذه الطريقة:
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () {
return Cache::get('key');
});
سنستخدم في كثير من الأمثلة الواجهات الساكنة لعرض عدة خاصيات لإطار العمل في توثيق Laravel.
متى نستخدم الواجهات الساكنة؟
للواجهات الساكنة فوائد كثيرة فهي توفِّر صيغةً مقتضبةً وسهلة التذكّر تسمح لنا باستخدام خاصيات Laravel دون حفظ أسماء الأصناف الطويلة التي تسلتزم إضافتها وإعدادها يدويًا. علاوة على ذلك، اختبارهن أسهل بفضل استخدامهن الفريد لدوال PHP الدَيناميكيَة.
يجب الاحتياط عند استخدام الواجهات الساكنة حيث أنّ خطرهم الرئيسي هو زحف مجال الصَنف (class scope). بما أن الواجهات السَاكنة سهلة الاستخدام ولا تتطلب إضافات، قد يسهل ترك صنفك يواصل التضخَم بشكل هام عند استخدام عدَة واجهات سَاكنة في صنف واحد. يمكن الحد من هذه المشكلة باستخدام إضافة الاعتماديات (dependency injection)، اذ ان التحذيرات المرئية التي تصدرها دالة بناء constructor ضخمة تعلمك ان صنفك تضخَّم أكثر من اللازم. لذلك أعر انتباهًا خاصًا لحجم صنفك كي يظل مجال مسؤوليته (scope of responsibility) ضيَقًا.
ملاحظة: عند بناء حزمة طرف ثالث تتعامل مع Laravel، من الأفضل إضافة عقود Laravel (Laravel contracts) بدل استخدام الواجهات الساكنة لأنّ الحزم المبنيّة خارج Laravel ذاته لن تستطيع استخدام مساعدي اختبار واجهات Laravel الساكنة (facade testing helpers)
الواجهات وإضافة الاعتماديّة (dependency injection)
القدرة على استبدال تعاريف استخدام (implementations) الصنف المضاف هي إحدى فوائد إضافة الاعتماديّة الأساسية. هذه الخاصية مفيدة عند الاختبار بما أنك تقدر على إضافة غرض مُقلِّد (mock) أو بذرة (stub) وتتحقق من استدعاء مختلف الدوال في تلك البذرة.
ليس من الممكن عادة استخدام الأغراض المُقلِّدة أو البذور على دالَة ساكنة فعلًا (static class method). مع ذلك، لمّا كانت الواجهات الساكنة تستخدم دوالًا ديناميكية لتوكيل استدعاء كائنات (objects) مستبينة من حاوي الخدمات، يمكننا اختبار الواجهات الساكنة تمامًا كما نختبر نسخة صنف مضاف. خذ مثلًا المسار الآتي:
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () {
return Cache::get('key');
});
يمكننا كتابة الاختبار التالي للتحقق من استدعاء الدالة Cache::get
بالمتغيَر الوسيط (argument) الذي توقعناه:
use Illuminate\Support\Facades\Cache;
/**
* مثال دالة بانية بسيطة.
*
* @return void
*/
public function testBasicExample()
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$this->visit('/cache')
->see('value');
}
الواجهات الساكنات والدوال البانية المساعدة (Helper Function)
إضافة للواجهات الساكنة، يتضمن Laravel عدة دوال بانية "مُساعدة" قادرة على تنفيذ مهام شائعة مثل توليد الواجهات (views)، وإطلاق الأحداث، وإرسال الأعمال (jobs)، أو إرسال ردود HTTP. تقوم عدَة دوال مُساعدة بنفس وظيفة الواجهة السَاكنة المناظرة. ففي المثال الآتي سيكون استدعاء هذه الواجهة هو نظير استدعاء الدالة المساعدة:
return View::make('profile');
return view('profile');
لا يوجد أي فرق تطبيقي بين الواجهات السَاكنة والدوال المُساعدة بتاتًا. تستطيع اختبار الدَالة ونظيرتها الواجهة الساكنة بنفس الطريقة بالضبط. فلنأخذ المسار التالي مثلًا:
Route::get('/cache', function () {
return cache('key');
});
مُساعد الذاكرة المؤقتة سيستدعي التابع get
على الصَنف الكامن وراء واجهة الذاكرة المؤقتة الساكنة وراء الكواليس. لذا نستطيع كتابة الاختبار التالي للتحقق من أن التابع استُدعِيَ بنفس المتغيَر الوسيط (argument) الذي نتوقَعه رغم أننا نستخدم الداَلة المساعدة:
use Illuminate\Support\Facades\Cache;
/**
* مثال دالة بانية بسيطة.
*
* @return void
*/
public function testBasicExample()
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$this->visit('/cache')
->see('value');
}
كيفية عمل الواجهات الساكنة
في تطبيقات Laravel، الواجهة الساكنة هي صنف يوفر الوصول لكائن من الحاوي. الآلية التي تسمح بحدوث هذا موجودة في الصنف Facade
. واجهات Laravel الساكنة إضافة لأي واجهة تنشئها ستوسِّع صنف Illuminate\Support\Facades\Facade
الأساسي.
يستغل صنف الواجهة الساكنة Facade
الأساسي الدالة السحرية ()callStatic__
لتأجيل الاستدعاء من الواجهة لكائن مُسْتَبْيَن من الحاوي. في المثال أدناه يُرسَل استدعاء نظام لذاكرة Laravel المؤقتة. بنظرة خاطفة على هذه التعليمات يمكن للمرء افتراض أن الدالة الساكنة get
استُدعِيَت على صنف ذاكرة التخزين المؤقتة Cache
:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* عرض ملف المستخدم الشخصي
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
$user = Cache::get('user:'.$id);
return view('profile', ['user' => $user]);
}
}
لاحظ كيف أننا "نستورد" واجهة ذاكرة التخزين المؤقتة Cache
قرب الجزء العلوي من الملف. هذه الواجهة بمثابة وكيل للوصول لتعريف الاستخدام (implementation) الكامن وراء واجهة Illuminate\Contracts\Cache\Factory
. سيمرر أي استدعاء نقوم به باستخدام الواجهة الساكنة للنسخة الكامنة وراء خدمة ذاكرة Laravel المؤقتة.
إن نظرنا لصنف Illuminate\Support\Facades\Cache
، سنرى أنه لا وجود للتابع الساكن get
:
class Cache extends Facade
{
/**
* تحصل على اسم المُكوِّن المُسجَل
*
* @return string
*/
protected static function getFacadeAccessor() { return 'cache'; }
}
بدلًا عن هذا، تُوسِّع واجهة ذاكرة التخزين المؤقتة الساكنة Cache
صنف الواجهة الساكنة الأساسي Facade
وتُعرًف التابع ()getFacadeAccessor
. وظيفة هذا التابع هي رد اسم ارتباط حاوي الخدمات. يستبين Laravel ارتباط الذاكرة المؤقتة cache
من حاوي الخدمات عندما يشير المستخدم لأي دالة ساكنة بواجهة ذاكرة التخزين المؤقتة الساكنة، ثم يُنفِّذ الدالة المطلوبة (في هذه الحالة get
) على ذاك الكائن.
الواجهات الساكنة في الوقت الحالي (Real-Time Facades)
يمكنك معالجة أي صنف في تطبيقك كما لو كان واجهة ساكنة باستخدام الواجهات الساكنة في الوقت الحالي. لتوضيح كيفية الاستخدام فلندرس بديلا. فلنفترض مثلًا أن لنَموذَجِنَا Podcast
التابع publish
. لكي ننشر podcast نحتاج لإضافة نسخة Publisher
:
<?php
namespace App;
use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;
class Podcast extends Model
{
/**
* Publish the podcast.
*
* @param Publisher $publisher
* @return void
*/
public function publish(Publisher $publisher)
{
$this->update(['publishing' => now()]);
$publisher->publish($this);
}
}
تسمح لنا إضافة تعريف استخدام للناشر للتابع باختبار الدالة بسهولة على انفراد بما أننا قادرون على تقليد (mock) الناشر المُضَاف. مع ذلك يستلزمنا أن نُمَرِّر نسخة من publisher في كل مرة نستدعي فيها التابع publish
. يمكننا الحفاظ على نفس القدرة على الاختبار دون الاضطرار إلى تمرير نسخة Publisher
صراحة (explicitly) باستخدام الواجهات الساكنة بالوقت الحالي.
لتوليد واجهات ساكنة بالوقت الحالي، أسبق مجال أسماء الصنف المُستَوْرَد بالكلمة Facades
:
<?php
namespace App;
use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;
class Podcast extends Model
{
/**
* Publish the podcast.
*
* @return void
*/
public function publish()
{
$this->update(['publishing' => now()]);
Publisher::publish($this);
}
}
يستبين تعريف استخدام الناشر من حاوي الخدمات باستخدام جزء الواجهة (interface) أو اسم الصنف الذي يظهر بعد استخدام واجهات ساكنة بالوقت الحالي بعد سابقة Facades
. يمكننا استخدام مُساعدي اختبار Laravel المُدمجات لتقليد استدعاء هذا التابع عند الاختبار:
<?php
namespace Tests\Feature;
use App\Podcast;
use Tests\TestCase;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;
class PodcastTest extends TestCase
{
use RefreshDatabase;
/**
* مثال اختبار
*
* @return void
*/
public function test_podcast_can_be_published()
{
$podcast = factory(Podcast::class)->create();
Publisher::shouldReceive('publish')->once()->with($podcast);
$podcast->publish();
}
}
مرجع صنف الواجهات الساكنة
الواجهة الساكنة (Facade) |
الصنف |
ارتباط حاوي الخدمات |
---|---|---|
App | Illuminate\Foundation\Application
|
app |
Artisan | Illuminate\Contracts\Console\Kernel
|
artisan |
Auth | Illuminate\Auth\AuthManager
|
auth |
(Auth (Instance | Illuminate\Contracts\Auth\Guard
|
auth.driver |
Blade | Illuminate\View\Compilers\BladeCompiler
|
blade.compiler |
Broadcast | Illuminate\Contracts\Broadcasting\Factory
|
|
(Broadcast (Instance | Illuminate\Contracts\Broadcasting\Broadcaster
|
|
Bus | Illuminate\Contracts\Bus\Dispatcher
|
|
Cache | Illuminate\Cache\CacheManager
|
cache |
(Cache (Instance | Illuminate\Cache\Repository
|
cache.store |
Config | Illuminate\Config\Repository
|
config |
Cookie | Illuminate\Cookie\CookieJar
|
cookie |
Crypt | Illuminate\Encryption\Encrypter
|
encrypter |
DB | Illuminate\Database\DatabaseManager
|
db |
(DB (Instance | Illuminate\Database\Connection
|
db.connection |
Event | Illuminate\Events\Dispatcher
|
events |
File | Illuminate\Filesystem\Filesystem
|
files |
Gate | Illuminate\Contracts\Auth\Access\Gate
|
|
Hash | Illuminate\Contracts\Hashing\Hasher
|
hash |
Lang | Illuminate\Translation\Translator
|
translator |
Log | Illuminate\Log\Logger
|
log |
Illuminate\Mail\Mailer
|
mailer | |
Notification | Illuminate\Notifications\ChannelManager
|
|
Password | Illuminate\Auth\Passwords\PasswordBrokerManager
|
auth.password |
(Password (Instance | Illuminate\Auth\Passwords\PasswordBroker
|
auth.password.broker |
Queue | Illuminate\Queue\QueueManager
|
queue |
(Queue (Instance | Illuminate\Contracts\Queue\Queue
|
queue.connection |
(Queue (Base Class | Illuminate\Queue\Queue
|
|
Redirect | Illuminate\Routing\Redirector
|
redirect |
Redis | Illuminate\Redis\RedisManager
|
redis |
(Redis (Instance | Illuminate\Redis\Connections\Connection
|
redis.connection |
Request | Illuminate\Http\Request
|
request |
Response | Illuminate\Contracts\Routing\ResponseFactory
|
|
(Response (Instance | Illuminate\Http\Response
|
|
Route | Illuminate\Routing\Router
|
router |
Schema | Illuminate\Database\Schema\Builder
|
|
Session | Illuminate\Session\SessionManager
|
session |
(Session (Instance | Illuminate\Session\Store
|
session.store |
Storage | Illuminate\Filesystem\FilesystemManager
|
filesystem |
(Storage (Instance | Illuminate\Contracts\Filesystem\Filesystem
|
filesystem.disk |
URL | Illuminate\Routing\UrlGenerator
|
url |
Validator | Illuminate\Validation\Factory
|
validator |
(Validator (Instance | Illuminate\Validation\Validator
|
|
View | Illuminate\View\Factory
|
view |
(View (Instance | Illuminate\View\View
|