الفرق بين المراجعتين لصفحة: «Laravel/facades»
تسنيم-ولهازي (نقاش | مساهمات) لا ملخص تعديل |
رؤيا-بنعطية (نقاش | مساهمات) لا ملخص تعديل |
||
سطر 198: | سطر 198: | ||
== مرجع صنف الواجهات الساكنة == | == مرجع صنف الواجهات الساكنة == | ||
{| class="wikitable" | {| class="wikitable" | ||
! | |||
== الواجهة الساكنة (Facade) == | == الواجهة الساكنة (Facade) == | ||
! | |||
== الصنف == | == الصنف == | ||
! | |||
== ارتباط حاوي الخدمات == | == ارتباط حاوي الخدمات == | ||
|- | |- | ||
سطر 217: | سطر 217: | ||
|auth | |auth | ||
|- | |- | ||
|Auth (Instance | |(Auth (Instance | ||
|Illuminate\Contracts\Auth\Guard | |Illuminate\Contracts\Auth\Guard | ||
|auth.driver | |auth.driver | ||
سطر 229: | سطر 229: | ||
| | | | ||
|- | |- | ||
|Broadcast (Instance | |(Broadcast (Instance | ||
|Illuminate\Contracts\Broadcasting\Broadcaster | |Illuminate\Contracts\Broadcasting\Broadcaster | ||
| | | | ||
سطر 241: | سطر 241: | ||
|cache | |cache | ||
|- | |- | ||
|Cache (Instance | |(Cache (Instance | ||
|Illuminate\Cache\Repository | |Illuminate\Cache\Repository | ||
|cache.store | |cache.store | ||
سطر 261: | سطر 261: | ||
|db | |db | ||
|- | |- | ||
|DB (Instance | |(DB (Instance | ||
|Illuminate\Database\Connection | |Illuminate\Database\Connection | ||
|db.connection | |db.connection | ||
سطر 301: | سطر 301: | ||
|auth.password | |auth.password | ||
|- | |- | ||
|Password (Instance | |(Password (Instance | ||
|Illuminate\Auth\Passwords\PasswordBroker | |Illuminate\Auth\Passwords\PasswordBroker | ||
|auth.password.broker | |auth.password.broker | ||
سطر 309: | سطر 309: | ||
|queue | |queue | ||
|- | |- | ||
|Queue (Instance | |(Queue (Instance | ||
|Illuminate\Contracts\Queue\Queue | |Illuminate\Contracts\Queue\Queue | ||
|queue.connection | |queue.connection | ||
|- | |- | ||
|Queue (Base Class | |(Queue (Base Class | ||
|Illuminate\Queue\Queue | |Illuminate\Queue\Queue | ||
| | | | ||
سطر 325: | سطر 325: | ||
|redis | |redis | ||
|- | |- | ||
|Redis (Instance | |(Redis (Instance | ||
|Illuminate\Redis\Connections\Connection | |Illuminate\Redis\Connections\Connection | ||
|redis.connection | |redis.connection | ||
سطر 337: | سطر 337: | ||
| | | | ||
|- | |- | ||
|Response (Instance | |(Response (Instance | ||
|Illuminate\Http\Response | |Illuminate\Http\Response | ||
| | | | ||
سطر 353: | سطر 353: | ||
|session | |session | ||
|- | |- | ||
|Session (Instance | |(Session (Instance | ||
|Illuminate\Session\Store | |Illuminate\Session\Store | ||
|session.store | |session.store | ||
سطر 361: | سطر 361: | ||
|filesystem | |filesystem | ||
|- | |- | ||
|Storage (Instance | |(Storage (Instance | ||
|Illuminate\Contracts\Filesystem\Filesystem | |Illuminate\Contracts\Filesystem\Filesystem | ||
|filesystem.disk | |filesystem.disk | ||
سطر 373: | سطر 373: | ||
|validator | |validator | ||
|- | |- | ||
|Validator (Instance | |(Validator (Instance | ||
|Illuminate\Validation\Validator | |Illuminate\Validation\Validator | ||
| | | | ||
سطر 381: | سطر 381: | ||
|view | |view | ||
|- | |- | ||
|View (Instance | |(View (Instance | ||
|Illuminate\View\View | |Illuminate\View\View | ||
| | | | ||
|} | |} | ||
== مصادر == | |||
* [https://laravel.com/docs/5.6/facades صفحة الواجهات الساكنة في توثيق Laravel الرسمي.] |
مراجعة 17:56، 5 أكتوبر 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 |