الفرق بين المراجعتين لصفحة: «Laravel/events»
رؤيا-بنعطية (نقاش | مساهمات) أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:الأحداث في Laravel}}</noinclude> تصنيف:Laravel تصنيف:Laravel Digging deeper' |
رؤيا-بنعطية (نقاش | مساهمات) لا ملخص تعديل |
||
سطر 2: | سطر 2: | ||
[[تصنيف:Laravel]] | [[تصنيف:Laravel]] | ||
[[تصنيف:Laravel Digging deeper]] | [[تصنيف:Laravel Digging deeper]] | ||
== مقدمة == | |||
توفّر أحداث [[Laravel]] تطبيق مراقب بسيط يسمح بالإشتراك والاستماع لعدّة أحداث يطلقها التطبيق. تُخزَّن أصناف الأحداث في الدليل <code>app/Events</code>، في حين توجد المنصتات في <code>app/Listeners</code>. لا تقلق إن لم تجد هذه الدلائل في التطبيق إذ تُصنع حين تولّد أحداثًا و منصتات باستعمال [[Laravel/artisan|أوامر artisan]]. | |||
الأحداث طريقة ممتازة لفك ارتباط عدّة عناصر من التطبيق حيث يمكن أن يكون لحدث واحد عدّة منصتات منفصلة كليا عن بعضها البعض. مثلًا، قد تريد إرسال إعلان slack للمستخدم كلما شحن طلب. بدل ربط معالجة الطلبات بخدمة slack، يمكنك إطلاق حدث <code>orderShipped</code> وجعل منصت ينتظره ويحوله لإعلان slack. | |||
== تسجيل الأحداث و المنصتات == | |||
يوفّر مزوّد الخدمات <code>EventServiceProvider</code> المضمَّن في تطبيقات [[Laravel]] مكانًا ملائمًا لتسجيل كل المنصتات على الأحداث. تحتوي الخاصية <code>listen</code> مصفوفة من كل الأحداث(مفاتيح) و المنصتات(قيم). طبعًا، يمكنك إضافة أي عدد من الأحداث يستحقّها التطبيق. مثلًا، فلنضف الحدث OrderShipped: | |||
/** | |||
<nowiki>*</nowiki>امنصتات على الأحداث. | |||
<nowiki>*</nowiki> | |||
<nowiki>*</nowiki> @var array | |||
<nowiki>*</nowiki>/ | |||
protected $listen = [ | |||
'App\Events\OrderShipped' => [ | |||
'App\Listeners\SendShipmentNotification', | |||
], | |||
]; | |||
=== توليد الأحداث والمنصتات === | |||
قد يكون إنشاء الملفات يدويًّا لكل حدث ومنصت عملًا مرهقًا. بدل ذلك، أضف الأحداث والمنصتات للملف EventServiceProvider واستعمل الأمر event:generate. سيولّد هذا الأمر كل الأحداث والمنصتات المذكورة في EventServiceProvider. طبعًا، الأحداث الموجودة مسبقًا لن تتغير: | |||
php artisan event:generate | |||
=== التسجيل اليدوي للأحداث === | |||
في العادة، يجب تسجيل الأحداث في المصفوفة listen$ من الملف EventServiceProvider. لكن، يمكن أيضا تسجيل نطاق مغلق Closure للأحداث يدويًّا في التابع boot من EventServiceProvider: | |||
/** | |||
<nowiki>*</nowiki>تسجيل أحداث إضافية. | |||
<nowiki>*</nowiki> | |||
<nowiki>*</nowiki> @return void | |||
<nowiki>*</nowiki>/ | |||
public function boot() | |||
{ | |||
parent::boot(); | |||
Event::listen('event.name', function ($foo, $bar) { | |||
// | |||
}); | |||
} | |||
=== منصتات الأحداث الشمولية === | |||
يمكن أيضا تسجيل منصتات الأحداث الشمولية باستعمال الرمز * كمعامل بديل. ممّا يسمح بالتقاط عدّة أحداث بمنصت واحد. تقبل المنصتات البديلة اسم حدث كمعامل أول وكامل مصفوفة بيانات الأحداث كمعامل ثاني: | |||
Event::listen('event.*', function ($eventName, array $data) { | |||
// | |||
}); | |||
== تعريف الأحداث == | |||
صنف الأحداث هو حاوي بيانات يحفظ المعلومات المتعلقة بالأحداث. لنفترض مثلًا أنّ الحدث OrderShipped يتلقّى كائن رابط الكائنات بالعلاقات Eloquent: | |||
<?php | |||
namespace App\Events; | |||
use App\Order; | |||
use Illuminate\Queue\SerializesModels; | |||
class OrderShipped | |||
{ | |||
use SerializesModels; | |||
public $order; | |||
/** | |||
* إنشاء حدث جديد | |||
* | |||
* @param \App\Order $order | |||
* @return void | |||
*/ | |||
public function __construct(Order $order) | |||
{ | |||
$this->order = $order; | |||
} | |||
} | |||
كما تلاحظ، لا يحتوي الصنف على أي عمل منطقي، هو فقط حامل لنسخة Order المتََحصَّل عليها. ستسلسل الخاصية SerializesModels كل نموذج Eloquent إذا تمّت سَلسَلة الحدث باستخدام دالة serialize PHP. | |||
== تعريف المنصتات == | |||
بعد ذلك، لنلق نظرة على منصت الحدث. تتلقى المنصتات نسخة حدث في التابع handle. يُحمّل الأمر event:generate تلقائيًّا صنف الحدث الملائم ويلمح إلى نوعه للتابع. يمكنك تحديد أي عمل تريد كإجابة للحدث في هذا التابع: | |||
<?php | |||
namespace App\Listeners; | |||
use App\Events\OrderShipped; | |||
class SendShipmentNotification | |||
{ | |||
/** | |||
* إنشاء المنصت * | |||
* @return void | |||
*/ | |||
public function __construct() | |||
{ | |||
// | |||
} | |||
/** | |||
* العمل على الحدث | |||
* | |||
* @param \App\Events\OrderShipped $event | |||
* @return void | |||
*/ | |||
public function handle(OrderShipped $event) | |||
{ | |||
// ولوج الطلب | |||
} | |||
} | |||
ملاحظة : يمكن للمنصت أيضًا التلميح إلى نوع ااعتماديات التي يحتاجها التابع الباني. كل المنصتات تعالَج في حاوي خدمات Laravel لذا تُضاف الإعتماديات آليًّا. | |||
==== إيقاف انتشار حدث ==== | |||
قد تريد في بعض الأحيان إيقاف انتشار حدث لمنصتات أخرى. يمكنك القيام بذلك بإرجاع القيمة false من التابع handle. | |||
== إضافة المنصتات للطابور == | |||
يكون صفّ المنصتات في الطابور مفي دًا إذا كانت المنصتات تقوم بعمل بطيء كإرسال بريد إلكتروني أو طلب HTTP. قبل البدء بصفّ المنصتات، تأكد من ضبط الطابور وإطلاق منصت على الطابور في الخادم أو في بيئة التطوير المحلية. | |||
لتحديد أنّ منصتا يجب إضافته للطابور، أضف الواجهة الثابتة ShouldQueue لصنف المنصت. تملك المنصتات المولّدة باستعمال الأمر event:generate هذه الواجهة منذ البدء محمَّلة في مساحة الإسم الحالية، لذا يمكنك استخدامها مباشرة: | |||
<?php | |||
namespace App\Listeners; | |||
use App\Events\OrderShipped; | |||
use Illuminate\Contracts\Queue\ShouldQueue; | |||
class SendShipmentNotification implements ShouldQueue | |||
{ | |||
// | |||
} | |||
الآن إذا نودي المنصت لحدث ما سيُضاف مباشرة للطابور. إن لم يُطلق أي استثناء عند تنفيذ المنصت من الطابور، ستُحذف المهمة عند انتهاء التنفيذ. | |||
=== تخصيص اتصال الطابور واسمه === | |||
إذا أردت تخصيص اسم الطابور والاتصال المستخدَم للمنصت. يمكنك استعمال الخاصيتين connection$ و queue$ في صنف المنصت: | |||
<?php | |||
namespace App\Listeners; | |||
use App\Events\OrderShipped; | |||
use Illuminate\Contracts\Queue\ShouldQueue; | |||
class SendShipmentNotification implements ShouldQueue | |||
{ | |||
/** | |||
* اسم الاتصال | |||
* | |||
* @var string|null | |||
*/ | |||
public $connection = 'sqs'; | |||
/** | |||
* اسم الطابور | |||
* | |||
* @var string|null | |||
*/ | |||
public $queue = 'listeners'; | |||
} | |||
=== الوصول إلى الطوابير يدويا === | |||
إذا احتجت للوصول يدويًّا إلى توابع الأعمال المصفوفة في الطوابير: delete و release، استخدم Illuminate\Queue\InteractsWithQueue. تُحمَّل هذه الخاصية تلقائيًّا مع المنصتات المولّدة وتمنح حرية استخدام التوابع delete و release: | |||
<?php | |||
namespace App\Listeners; | |||
use App\Events\OrderShipped; | |||
use Illuminate\Queue\InteractsWithQueue; | |||
use Illuminate\Contracts\Queue\ShouldQueue; | |||
class SendShipmentNotification implements ShouldQueue | |||
{ | |||
use InteractsWithQueue; | |||
/** | |||
* معالجة الحدث * | |||
* @param \App\Events\OrderShipped $event | |||
* @return void | |||
*/ | |||
public function handle(OrderShipped $event) | |||
{ | |||
if (true) { | |||
$this->release(30); | |||
} | |||
} | |||
} | |||
=== معالجة الأعمال الفاشلة === | |||
قد يفشل تنفيذ بعض المهام في الطابور. إذا تجاوز المنصت عدد المحاولات الأقصى المحدد للطابور، ينادى التابع failed من المنصت. يتلقى التابع failed نسخة من الاستثناء الذي سبب الفشل: | |||
namespace App\Listeners; | |||
use App\Events\OrderShipped; | |||
use Illuminate\Queue\InteractsWithQueue; | |||
use Illuminate\Contracts\Queue\ShouldQueue; | |||
class SendShipmentNotification implements ShouldQueue | |||
{ | |||
use InteractsWithQueue; | |||
/** | |||
* معالجة الحدث | |||
* | |||
* @param \App\Events\OrderShipped $event | |||
* @return void | |||
*/ | |||
public function handle(OrderShipped $event) | |||
{ | |||
// | |||
} | |||
/** | |||
* معالجة العمل الفاشل | |||
* | |||
* @param \App\Events\OrderShipped $event | |||
* @param \Exception $exception | |||
* @return void | |||
*/ | |||
public function failed(OrderShipped $event, $exception) | |||
{ | |||
// | |||
} | |||
} | |||
== إرسال الأحداث == | |||
لإرسال حدث، مرّر نسخة منه للمساعد event. سيُطلق المساعد لكل المنصتات المسجّلة. حيث أنّ المساعد عامّ يمكن استخدامه من كامل التطبيق: | |||
<?php | |||
namespace App\Http\Controllers; | |||
use App\Order; | |||
use App\Events\OrderShipped; | |||
use App\Http\Controllers\Controller; | |||
class OrderController extends Controller | |||
{ | |||
/** | |||
* تحميل طلب معين. | |||
* | |||
* @param int $orderId | |||
* @return Response | |||
*/ | |||
public function ship($orderId) | |||
{ | |||
$order = Order::findOrFail($orderId); | |||
//منطق تحميل الطلبات | |||
event(new OrderShipped($order)); | |||
} | |||
} | |||
ملاحظة : عند الاختبار، من المفيد التأكد من إطلاق الأحداث دون تشغيل منصتاتها. مساعدات الاختبار المضمّنة في Laravel تجعل هذا ممكنًا. | |||
== الاشتراك في الأحداث == | |||
=== كتابة مشتركات الأحداث === | |||
مشتركات الأحداث هي أصناف يمكنها الاشتراك في أحداث عديدة من داخل الصنف نفسه. مما يسمح بتعريف عدّة معالجات (handlers) في صنف واحد. يجب على المشتركات تعريف التابع subscribe، الذي يقبل نسخة من مطلق الأحداث. يمكن نداء call مع مطلق أحداث معين لتسجيل منصتات الحدث: | |||
<?php | |||
namespace App\Listeners; | |||
class UserEventSubscriber | |||
{ | |||
/** | |||
* معالجة أحداث تسجيل دخول المستخدم */ | |||
public function onUserLogin($event) {} | |||
/** | |||
* معالجة أحداث تسجيل خروج المستخدم */ | |||
public function onUserLogout($event) {} | |||
/** | |||
* تسجيل المنصتات للمشترك | |||
* | |||
* @param \Illuminate\Events\Dispatcher $events | |||
*/ | |||
public function subscribe($events) | |||
{ | |||
$events->listen( | |||
'Illuminate\Auth\Events\Login', | |||
'App\Listeners\UserEventSubscriber@onUserLogin' | |||
); | |||
$events->listen( | |||
'Illuminate\Auth\Events\Logout', | |||
'App\Listeners\UserEventSubscriber@onUserLogout' | |||
); | |||
} | |||
} | |||
=== تسجيل مشتركات الأحداث === | |||
بعد كتابة المشتركات، أنت جاهز لتسجيلها في مطلق الأحداث. يتم التسجيل باستعمال الخاصية subscribe$ من EventServiceProvider. مثلا، لنضف UserEventSubscriber للقائمة: | |||
<?php | |||
namespace App\Providers; | |||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; | |||
class EventServiceProvider extends ServiceProvider | |||
{ | |||
/** | |||
* عمليات ربط منصت الحدث | |||
* | |||
* @var array | |||
*/ | |||
protected $listen = [ | |||
// | |||
]; | |||
/** | |||
*صنف المشترك للتسجيل | |||
* | |||
* @var array | |||
*/ | |||
protected $subscribe = [ | |||
'App\Listeners\UserEventSubscriber', | |||
]; | |||
} | |||
== مصادر == | |||
* صفحة Events من توثيق Laravel الرسمي. |
مراجعة 15:33، 19 أكتوبر 2018
مقدمة
توفّر أحداث Laravel تطبيق مراقب بسيط يسمح بالإشتراك والاستماع لعدّة أحداث يطلقها التطبيق. تُخزَّن أصناف الأحداث في الدليل app/Events
، في حين توجد المنصتات في app/Listeners
. لا تقلق إن لم تجد هذه الدلائل في التطبيق إذ تُصنع حين تولّد أحداثًا و منصتات باستعمال أوامر artisan.
الأحداث طريقة ممتازة لفك ارتباط عدّة عناصر من التطبيق حيث يمكن أن يكون لحدث واحد عدّة منصتات منفصلة كليا عن بعضها البعض. مثلًا، قد تريد إرسال إعلان slack للمستخدم كلما شحن طلب. بدل ربط معالجة الطلبات بخدمة slack، يمكنك إطلاق حدث orderShipped
وجعل منصت ينتظره ويحوله لإعلان slack.
تسجيل الأحداث و المنصتات
يوفّر مزوّد الخدمات EventServiceProvider
المضمَّن في تطبيقات Laravel مكانًا ملائمًا لتسجيل كل المنصتات على الأحداث. تحتوي الخاصية listen
مصفوفة من كل الأحداث(مفاتيح) و المنصتات(قيم). طبعًا، يمكنك إضافة أي عدد من الأحداث يستحقّها التطبيق. مثلًا، فلنضف الحدث OrderShipped:
/**
*امنصتات على الأحداث.
*
* @var array
*/
protected $listen = [
'App\Events\OrderShipped' => [
'App\Listeners\SendShipmentNotification',
],
];
توليد الأحداث والمنصتات
قد يكون إنشاء الملفات يدويًّا لكل حدث ومنصت عملًا مرهقًا. بدل ذلك، أضف الأحداث والمنصتات للملف EventServiceProvider واستعمل الأمر event:generate. سيولّد هذا الأمر كل الأحداث والمنصتات المذكورة في EventServiceProvider. طبعًا، الأحداث الموجودة مسبقًا لن تتغير:
php artisan event:generate
التسجيل اليدوي للأحداث
في العادة، يجب تسجيل الأحداث في المصفوفة listen$ من الملف EventServiceProvider. لكن، يمكن أيضا تسجيل نطاق مغلق Closure للأحداث يدويًّا في التابع boot من EventServiceProvider:
/**
*تسجيل أحداث إضافية.
*
* @return void
*/
public function boot()
{
parent::boot();
Event::listen('event.name', function ($foo, $bar) {
//
});
}
منصتات الأحداث الشمولية
يمكن أيضا تسجيل منصتات الأحداث الشمولية باستعمال الرمز * كمعامل بديل. ممّا يسمح بالتقاط عدّة أحداث بمنصت واحد. تقبل المنصتات البديلة اسم حدث كمعامل أول وكامل مصفوفة بيانات الأحداث كمعامل ثاني:
Event::listen('event.*', function ($eventName, array $data) {
//
});
تعريف الأحداث
صنف الأحداث هو حاوي بيانات يحفظ المعلومات المتعلقة بالأحداث. لنفترض مثلًا أنّ الحدث OrderShipped يتلقّى كائن رابط الكائنات بالعلاقات Eloquent:
<?php
namespace App\Events;
use App\Order;
use Illuminate\Queue\SerializesModels;
class OrderShipped
{
use SerializesModels;
public $order;
/**
* إنشاء حدث جديد
*
* @param \App\Order $order
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
}
كما تلاحظ، لا يحتوي الصنف على أي عمل منطقي، هو فقط حامل لنسخة Order المتََحصَّل عليها. ستسلسل الخاصية SerializesModels كل نموذج Eloquent إذا تمّت سَلسَلة الحدث باستخدام دالة serialize PHP.
تعريف المنصتات
بعد ذلك، لنلق نظرة على منصت الحدث. تتلقى المنصتات نسخة حدث في التابع handle. يُحمّل الأمر event:generate تلقائيًّا صنف الحدث الملائم ويلمح إلى نوعه للتابع. يمكنك تحديد أي عمل تريد كإجابة للحدث في هذا التابع:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
class SendShipmentNotification
{
/**
* إنشاء المنصت *
* @return void
*/
public function __construct()
{
//
}
/**
* العمل على الحدث
*
* @param \App\Events\OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
// ولوج الطلب
}
}
ملاحظة : يمكن للمنصت أيضًا التلميح إلى نوع ااعتماديات التي يحتاجها التابع الباني. كل المنصتات تعالَج في حاوي خدمات Laravel لذا تُضاف الإعتماديات آليًّا.
إيقاف انتشار حدث
قد تريد في بعض الأحيان إيقاف انتشار حدث لمنصتات أخرى. يمكنك القيام بذلك بإرجاع القيمة false من التابع handle.
إضافة المنصتات للطابور
يكون صفّ المنصتات في الطابور مفي دًا إذا كانت المنصتات تقوم بعمل بطيء كإرسال بريد إلكتروني أو طلب HTTP. قبل البدء بصفّ المنصتات، تأكد من ضبط الطابور وإطلاق منصت على الطابور في الخادم أو في بيئة التطوير المحلية.
لتحديد أنّ منصتا يجب إضافته للطابور، أضف الواجهة الثابتة ShouldQueue لصنف المنصت. تملك المنصتات المولّدة باستعمال الأمر event:generate هذه الواجهة منذ البدء محمَّلة في مساحة الإسم الحالية، لذا يمكنك استخدامها مباشرة:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
//
}
الآن إذا نودي المنصت لحدث ما سيُضاف مباشرة للطابور. إن لم يُطلق أي استثناء عند تنفيذ المنصت من الطابور، ستُحذف المهمة عند انتهاء التنفيذ.
تخصيص اتصال الطابور واسمه
إذا أردت تخصيص اسم الطابور والاتصال المستخدَم للمنصت. يمكنك استعمال الخاصيتين connection$ و queue$ في صنف المنصت:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
/**
* اسم الاتصال
*
* @var string|null
*/
public $connection = 'sqs';
/**
* اسم الطابور
*
* @var string|null
*/
public $queue = 'listeners';
}
الوصول إلى الطوابير يدويا
إذا احتجت للوصول يدويًّا إلى توابع الأعمال المصفوفة في الطوابير: delete و release، استخدم Illuminate\Queue\InteractsWithQueue. تُحمَّل هذه الخاصية تلقائيًّا مع المنصتات المولّدة وتمنح حرية استخدام التوابع delete و release:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
/**
* معالجة الحدث *
* @param \App\Events\OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
if (true) {
$this->release(30);
}
}
}
معالجة الأعمال الفاشلة
قد يفشل تنفيذ بعض المهام في الطابور. إذا تجاوز المنصت عدد المحاولات الأقصى المحدد للطابور، ينادى التابع failed من المنصت. يتلقى التابع failed نسخة من الاستثناء الذي سبب الفشل:
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
/**
* معالجة الحدث
*
* @param \App\Events\OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
//
}
/**
* معالجة العمل الفاشل
*
* @param \App\Events\OrderShipped $event
* @param \Exception $exception
* @return void
*/
public function failed(OrderShipped $event, $exception)
{
//
}
}
إرسال الأحداث
لإرسال حدث، مرّر نسخة منه للمساعد event. سيُطلق المساعد لكل المنصتات المسجّلة. حيث أنّ المساعد عامّ يمكن استخدامه من كامل التطبيق:
<?php
namespace App\Http\Controllers;
use App\Order;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
class OrderController extends Controller
{
/**
* تحميل طلب معين.
*
* @param int $orderId
* @return Response
*/
public function ship($orderId)
{
$order = Order::findOrFail($orderId);
//منطق تحميل الطلبات
event(new OrderShipped($order));
}
}
ملاحظة : عند الاختبار، من المفيد التأكد من إطلاق الأحداث دون تشغيل منصتاتها. مساعدات الاختبار المضمّنة في Laravel تجعل هذا ممكنًا.
الاشتراك في الأحداث
كتابة مشتركات الأحداث
مشتركات الأحداث هي أصناف يمكنها الاشتراك في أحداث عديدة من داخل الصنف نفسه. مما يسمح بتعريف عدّة معالجات (handlers) في صنف واحد. يجب على المشتركات تعريف التابع subscribe، الذي يقبل نسخة من مطلق الأحداث. يمكن نداء call مع مطلق أحداث معين لتسجيل منصتات الحدث:
<?php
namespace App\Listeners;
class UserEventSubscriber
{
/**
* معالجة أحداث تسجيل دخول المستخدم */
public function onUserLogin($event) {}
/**
* معالجة أحداث تسجيل خروج المستخدم */
public function onUserLogout($event) {}
/**
* تسجيل المنصتات للمشترك
*
* @param \Illuminate\Events\Dispatcher $events
*/
public function subscribe($events)
{
$events->listen(
'Illuminate\Auth\Events\Login',
'App\Listeners\UserEventSubscriber@onUserLogin'
);
$events->listen(
'Illuminate\Auth\Events\Logout',
'App\Listeners\UserEventSubscriber@onUserLogout'
);
}
}
تسجيل مشتركات الأحداث
بعد كتابة المشتركات، أنت جاهز لتسجيلها في مطلق الأحداث. يتم التسجيل باستعمال الخاصية subscribe$ من EventServiceProvider. مثلا، لنضف UserEventSubscriber للقائمة:
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* عمليات ربط منصت الحدث
*
* @var array
*/
protected $listen = [
//
];
/**
*صنف المشترك للتسجيل
*
* @var array
*/
protected $subscribe = [
'App\Listeners\UserEventSubscriber',
];
}
مصادر
- صفحة Events من توثيق Laravel الرسمي.