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

من موسوعة حسوب
أنشأ الصفحة ب' == مقدمة == تُوفِّر الواجهات الساكنة واجهة "ساكنة" (static) للأصناف المتوافرة في حاوي خدمات تطبيقك...'
 
ط استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}'
 
(9 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
 
<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) ضيَقًا.


'''<u>ملاحظة</u>''': عند بناء حزمة طرف ثالث تتعامل مع Laravel، من الأفضل إضافة عقود Laravel ‏(Laravel contracts) بدل استخدام الواجهات الساكنة لأنّ الحزم المبنيّة خارج Laravel ذاته لن تستطيع استخدام مساعدي اختبار واجهات Laravel الساكنة (facade testing helpers)
'''ملاحظة''': عند بناء حزمة طرف ثالث تتعامل مع Laravel، من الأفضل إضافة [[Laravel/contracts|عقود Laravel]] ‏(Laravel contracts) بدل استخدام الواجهات الساكنة لأنّ الحزم المبنيّة خارج [[Laravel]] ذاته لن تستطيع استخدام مساعدي اختبار واجهات Laravel الساكنة (facade testing helpers)


=== الواجهات وإضافة الاعتماديّة (dependency injection) ===
=== الواجهات وإضافة الاعتماديّة (dependency injection) ===
سطر 47: سطر 47:


=== الواجهات الساكنات والدوال البانية المساعدة (Helper Function) ===
=== الواجهات الساكنات والدوال البانية المساعدة (Helper Function) ===
إضافة للواجهات الساكنة، يتضمن Laravel عدة دوال بانية "مُساعدة" قادرة على تنفيذ مهام شائعة مثل توليد العروض (views)، وإطلاق الأحداث، وإرسال الأعمال (jobs)، أو إرسال ردود HTTP. تقوم عدَة دوال مُساعدة بنفس وظيفة الواجهة السَاكنة المناظرة. ففي المثال الآتي سيكون استدعاء هذه الواجهة هو نظير استدعاء الدالة المساعدة:<syntaxhighlight lang="php">
إضافة للواجهات الساكنة، يتضمن [[Laravel]] عدة دوال بانية "مُساعدة" قادرة على تنفيذ مهام شائعة مثل توليد الواجهات (views)، وإطلاق الأحداث، وإرسال الأعمال (jobs)، أو إرسال ردود HTTP. تقوم عدَة دوال مُساعدة بنفس وظيفة الواجهة السَاكنة المناظرة. ففي المثال الآتي سيكون استدعاء هذه الواجهة هو نظير استدعاء الدالة المساعدة:<syntaxhighlight lang="php">
return View::make('profile');
return View::make('profile');


سطر 55: سطر 55:
     return cache('key');
     return cache('key');
});
});
</syntaxhighlight>مُساعد الذاكرة المؤقتة سيستدعي الدَالة <code>get</code> على الصَنف الكامن وراء واجهة الذاكرة المؤقتة الساكنة وراء الكواليس. لذا نستطيع كتابة الاختبار التالي للتحقق من أن الدالة استُدعِيَت بنفس المتغيَر الوسيط (argument) الذي نتوقَعه رغم أننا نستخدم الداَلة المساعدة:<syntaxhighlight lang="php">
</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> الأساسي.
في تطبيقات [[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>get</code>:<syntaxhighlight lang="php">
إن نظرنا لصنف <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> وتُعرًف الدالة <code>()getFacadeAccessor</code>. وظيفة هذه الدالة هي رد اسم ارتباط حاوي الخدمات. يستبين Laravel ارتباط الذاكرة المؤقتة <code>cache</code> من حاوي الخدمات عندما يشير المستخدم لأي دالة ساكنة بواجهة ذاكرة التخزين المؤقتة الساكنة، ثم يُنفِّذ الدالة المطلوبة (في هذه الحالة <code>get</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>publish</code>. لكي ننشر podcast نحتاج لإضافة نسخة <code>Publisher</code> :<syntaxhighlight lang="php">
يمكنك معالجة أي صنف في تطبيقك كما لو كان واجهة ساكنة باستخدام الواجهات الساكنة في الوقت الحالي. لتوضيح كيفية الاستخدام فلندرس بديلا. فلنفترض مثلًا أن لنَموذَجِنَا <code>Podcast</code> التابع <code>publish</code>. لكي ننشر podcast نحتاج لإضافة نسخة <code>Publisher</code> :<syntaxhighlight lang="php">
<?php
<?php


سطر 140: سطر 140:
}
}


</syntaxhighlight>تسمح لنا إضافة تعريف استخدام للناشر للدالة باختبار الدالة بسهولة على انفراد بما أننا قادرون على تقليد (mock) الناشر المُضَاف. مع ذلك يستلزمنا أن نُمَرِّر نسخة من publisher في كل مرة نستدعي فيها الدالة <code>publish</code>. يمكننا الحفاظ على نفس القدرة على الاختبار دون الاضطرار إلى تمرير نسخة <code>Publisher</code> صراحة (explicitly)  باستخدام الواجهات الساكنة بالوقت الحالي.
</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 lang="php">
</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
Mail 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

مصادر