الفرق بين المراجعتين ل"Laravel/events"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
 
(6 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الأحداث في Laravel}}</noinclude>
+
<noinclude>{{DISPLAYTITLE:الأحداث (Events) في Laravel}}</noinclude>
[[تصنيف:Laravel]]
+
[[تصنيف:Laravel|{{SUBPAGENAME}}]]
[[تصنيف:Laravel Digging deeper]]
+
[[تصنيف:Laravel Digging deeper|{{SUBPAGENAME}}]]
 
== مقدمة ==
 
== مقدمة ==
 
توفّر أحداث [[Laravel]] تطبيق مراقب بسيط  يسمح بالإشتراك والاستماع لعدّة أحداث يطلقها التطبيق. تُخزَّن أصناف الأحداث في الدليل <code>app/Events</code>، في حين توجد المنصتات في <code>app/Listeners</code>. لا تقلق إن لم تجد هذه الدلائل في التطبيق إذ تُصنع حين تولّد أحداثًا و منصتات باستعمال [[Laravel/artisan|أوامر artisan]].
 
توفّر أحداث [[Laravel]] تطبيق مراقب بسيط  يسمح بالإشتراك والاستماع لعدّة أحداث يطلقها التطبيق. تُخزَّن أصناف الأحداث في الدليل <code>app/Events</code>، في حين توجد المنصتات في <code>app/Listeners</code>. لا تقلق إن لم تجد هذه الدلائل في التطبيق إذ تُصنع حين تولّد أحداثًا و منصتات باستعمال [[Laravel/artisan|أوامر artisan]].
سطر 31: سطر 31:
  
 
=== التسجيل اليدوي للأحداث ===
 
=== التسجيل اليدوي للأحداث ===
في العادة، يجب تسجيل الأحداث في المصفوفة <code>listen$</code> من الملف EventServiceProvider. لكن، يمكن أيضا تسجيل نطاق مغلق Closure للأحداث يدويًّا في التابع <code>boot</code> من EventServiceProvider:<syntaxhighlight lang="php">
+
في العادة، يجب تسجيل الأحداث في المصفوفة <code>listen$</code> من الملف EventServiceProvider. لكن، يمكن أيضا تسجيل نطاق مغلق Closure للأحداث يدويًّا في التابع <code>boot</code> من <code>EventServiceProvider</code>:<syntaxhighlight lang="php">
 
/**
 
/**
 
*تسجيل أحداث إضافية.
 
*تسجيل أحداث إضافية.
سطر 63: سطر 63:
  
 
== تعريف الأحداث ==
 
== تعريف الأحداث ==
صنف الأحداث هو حاوي بيانات يحفظ المعلومات المتعلقة بالأحداث. لنفترض مثلًا أنّ الحدث <code>OrderShipped</code> يتلقّى كائن رابط الكائنات بالعلاقات [[Laravel/eloquent|Eloquent]]:
+
صنف الأحداث هو حاوي بيانات يحفظ المعلومات المتعلقة بالأحداث. لنفترض مثلًا أنّ الحدث <code>OrderShipped</code> يتلقّى كائن رابط الكائنات بالعلاقات [[Laravel/eloquent|Eloquent]]:<syntaxhighlight lang="php">
 
+
<?php  
<?php
 
 
 
 
namespace App\Events;
 
namespace App\Events;
 
 
use App\Order;
 
use App\Order;
 
 
use Illuminate\Queue\SerializesModels;
 
use Illuminate\Queue\SerializesModels;
  
 
class OrderShipped
 
class OrderShipped
 
 
{
 
{
  
 
   use SerializesModels;
 
   use SerializesModels;
 
 
   public $order;
 
   public $order;
  
 
   /**
 
   /**
 
 
    * إنشاء حدث جديد
 
    * إنشاء حدث جديد
 
 
    *
 
    *
 
 
    * @param  \App\Order  $order
 
    * @param  \App\Order  $order
 
 
    * @return void
 
    * @return void
 
 
    */
 
    */
  
 
   public function __construct(Order $order)
 
   public function __construct(Order $order)
 
 
   {
 
   {
 
 
       $this->order = $order;
 
       $this->order = $order;
 
 
   }
 
   }
 +
}
  
}
 
  
كما تلاحظ، لا يحتوي الصنف على أي عمل منطقي، هو فقط حامل لنسخة Order المتََحصَّل عليها. ستسلسل الخاصية SerializesModels كل نموذج Eloquent إذا تمّت سَلسَلة الحدث باستخدام دالة serialize PHP.  
+
</syntaxhighlight>كما تلاحظ، لا يحتوي الصنف على أي عمل منطقي، هو فقط حامل لنسخة Order المتََحصَّل عليها. ستسلسل الخاصية <code>SerializesModels</code> كل نموذج [[Laravel/eloquent|Eloquent]] إذا تمّت سَلسَلة الحدث باستخدام دالة <code>[[PHP/serialize|serialize]]</code> [[PHP]].  
  
 
== تعريف المنصتات ==
 
== تعريف المنصتات ==
بعد ذلك، لنلق نظرة على منصت الحدث. تتلقى المنصتات نسخة حدث في التابع handle. يُحمّل الأمر event:generate تلقائيًّا صنف الحدث الملائم ويلمح إلى نوعه للتابع. يمكنك تحديد أي عمل تريد كإجابة للحدث في هذا التابع:
+
بعد ذلك، لنلق نظرة على منصت الحدث. تتلقى المنصتات نسخة حدث في التابع <code>handle</code>. يُحمّل الأمر <code>event:generate</code> تلقائيًّا صنف الحدث الملائم ويلمح إلى نوعه للتابع. يمكنك تحديد أي عمل تريد كإجابة للحدث في هذا التابع:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
 
 
namespace App\Listeners;
 
namespace App\Listeners;
 
 
use App\Events\OrderShipped;
 
use App\Events\OrderShipped;
  
سطر 117: سطر 100:
  
 
{
 
{
 
 
   /**
 
   /**
 
 
    * إنشاء المنصت     *
 
    * إنشاء المنصت     *
 
 
    * @return void
 
    * @return void
 
 
    */
 
    */
  
سطر 129: سطر 108:
  
 
   {
 
   {
 
 
      //
 
      //
 
 
   }
 
   }
  
 
   /**
 
   /**
 
 
    * العمل على الحدث
 
    * العمل على الحدث
 
 
    *
 
    *
 
 
    * @param  \App\Events\OrderShipped  $event
 
    * @param  \App\Events\OrderShipped  $event
 
 
    * @return void
 
    * @return void
 
 
    */
 
    */
  
 
   public function handle(OrderShipped $event)
 
   public function handle(OrderShipped $event)
 
 
   {
 
   {
  
سطر 153: سطر 124:
  
 
   }
 
   }
 +
}
 +
  
}
+
</syntaxhighlight>
  
ملاحظة : يمكن للمنصت أيضًا التلميح إلى نوع ااعتماديات التي يحتاجها التابع الباني. كل المنصتات تعالَج في حاوي خدمات Laravel لذا تُضاف الإعتماديات آليًّا.
+
ملاحظة : يمكن للمنصت أيضًا التلميح إلى نوع ااعتماديات التي يحتاجها التابع الباني. كل المنصتات تعالَج في [[Laravel/container|حاوي خدمات Laravel]] لذا تُضاف الإعتماديات آليًّا.
  
 
==== إيقاف انتشار حدث ====
 
==== إيقاف انتشار حدث ====
قد تريد في بعض الأحيان إيقاف انتشار حدث لمنصتات أخرى. يمكنك القيام بذلك بإرجاع القيمة false من التابع handle.
+
قد تريد في بعض الأحيان إيقاف انتشار حدث لمنصتات أخرى. يمكنك القيام بذلك بإرجاع القيمة <code>false</code> من التابع <code>handle</code>.
  
 
== إضافة المنصتات للطابور ==
 
== إضافة المنصتات للطابور ==
 
يكون صفّ المنصتات في الطابور مفي دًا إذا كانت المنصتات تقوم بعمل بطيء كإرسال بريد إلكتروني أو طلب HTTP. قبل البدء بصفّ المنصتات، تأكد من ضبط الطابور وإطلاق منصت على الطابور في الخادم أو في بيئة التطوير المحلية.
 
يكون صفّ المنصتات في الطابور مفي دًا إذا كانت المنصتات تقوم بعمل بطيء كإرسال بريد إلكتروني أو طلب HTTP. قبل البدء بصفّ المنصتات، تأكد من ضبط الطابور وإطلاق منصت على الطابور في الخادم أو في بيئة التطوير المحلية.
  
لتحديد أنّ منصتا يجب إضافته للطابور، أضف الواجهة الثابتة ShouldQueue لصنف المنصت. تملك المنصتات المولّدة باستعمال الأمر  event:generate هذه الواجهة منذ البدء محمَّلة في مساحة الإسم الحالية، لذا يمكنك استخدامها مباشرة:
+
لتحديد أنّ منصتا يجب إضافته للطابور، أضف الواجهة الثابتة <code>ShouldQueue</code> لصنف المنصت. تملك المنصتات المولّدة باستعمال الأمر  <code>event:generate</code> هذه الواجهة منذ البدء محمَّلة في مساحة الإسم الحالية، لذا يمكنك استخدامها مباشرة:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
  
سطر 171: سطر 143:
  
 
use App\Events\OrderShipped;
 
use App\Events\OrderShipped;
 
 
use Illuminate\Contracts\Queue\ShouldQueue;
 
use Illuminate\Contracts\Queue\ShouldQueue;
  
سطر 177: سطر 148:
  
 
{
 
{
 
 
  //
 
  //
 +
}
  
}
 
  
الآن إذا نودي المنصت لحدث ما سيُضاف مباشرة للطابور. إن لم يُطلق أي استثناء عند تنفيذ المنصت من الطابور، ستُحذف المهمة عند انتهاء التنفيذ.
+
</syntaxhighlight>الآن إذا نودي المنصت لحدث ما سيُضاف مباشرة للطابور. إن لم يُطلق أي استثناء عند تنفيذ المنصت من الطابور، ستُحذف المهمة عند انتهاء التنفيذ.
  
 
=== تخصيص اتصال الطابور واسمه ===
 
=== تخصيص اتصال الطابور واسمه ===
إذا أردت تخصيص اسم الطابور والاتصال المستخدَم للمنصت. يمكنك استعمال الخاصيتين connection$ و queue$ في صنف المنصت:
+
إذا أردت تخصيص اسم الطابور والاتصال المستخدَم للمنصت. يمكنك استعمال الخاصيتين <code>connection$</code> و <code>queue$</code> في صنف المنصت:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
 
 
namespace App\Listeners;
 
namespace App\Listeners;
  
 
use App\Events\OrderShipped;
 
use App\Events\OrderShipped;
 
 
use Illuminate\Contracts\Queue\ShouldQueue;
 
use Illuminate\Contracts\Queue\ShouldQueue;
  
سطر 200: سطر 167:
  
 
   /**
 
   /**
 
 
    * اسم الاتصال
 
    * اسم الاتصال
 
 
    *
 
    *
 
 
    * @var string|null
 
    * @var string|null
 
 
    */
 
    */
  
سطر 212: سطر 175:
  
 
   /**
 
   /**
 
 
    * اسم الطابور
 
    * اسم الطابور
 
 
    *
 
    *
 
 
    * @var string|null
 
    * @var string|null
 
 
    */
 
    */
  
سطر 224: سطر 183:
  
 
}
 
}
 +
 +
 +
</syntaxhighlight>
  
 
=== الوصول إلى الطوابير يدويا ===
 
=== الوصول إلى الطوابير يدويا ===
إذا احتجت للوصول يدويًّا إلى توابع الأعمال المصفوفة في الطوابير: delete و release، استخدم Illuminate\Queue\InteractsWithQueue. تُحمَّل هذه الخاصية تلقائيًّا مع المنصتات المولّدة وتمنح حرية استخدام التوابع delete و release:
+
إذا احتجت للوصول يدويًّا إلى توابع الأعمال المصفوفة في الطوابير: <code>delete</code> و <code>release</code>، استخدم <code>Illuminate\Queue\InteractsWithQueue</code>. تُحمَّل هذه الخاصية تلقائيًّا مع المنصتات المولّدة وتمنح حرية استخدام التوابع <code>delete</code> و <code>release</code>:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
  
سطر 233: سطر 194:
  
 
use App\Events\OrderShipped;
 
use App\Events\OrderShipped;
 
 
use Illuminate\Queue\InteractsWithQueue;
 
use Illuminate\Queue\InteractsWithQueue;
 
 
use Illuminate\Contracts\Queue\ShouldQueue;
 
use Illuminate\Contracts\Queue\ShouldQueue;
  
 
class SendShipmentNotification implements ShouldQueue
 
class SendShipmentNotification implements ShouldQueue
 
 
{
 
{
  
سطر 245: سطر 203:
  
 
   /**
 
   /**
 
 
    * معالجة الحدث     *
 
    * معالجة الحدث     *
 
 
    * @param  \App\Events\OrderShipped  $event
 
    * @param  \App\Events\OrderShipped  $event
 
 
    * @return void
 
    * @return void
 
 
    */
 
    */
  
سطر 257: سطر 211:
  
 
   {
 
   {
 
 
       if (true) {
 
       if (true) {
 
 
           $this->release(30);
 
           $this->release(30);
 
 
       }
 
       }
 +
   }
 +
}
  
   }
 
  
}
+
</syntaxhighlight>
  
 
=== معالجة الأعمال الفاشلة ===
 
=== معالجة الأعمال الفاشلة ===
قد يفشل تنفيذ بعض المهام في الطابور. إذا تجاوز المنصت عدد المحاولات الأقصى المحدد للطابور،  ينادى التابع failed من المنصت. يتلقى التابع failed نسخة من الاستثناء الذي سبب الفشل:
+
قد يفشل تنفيذ بعض المهام في الطابور. إذا تجاوز المنصت عدد المحاولات الأقصى المحدد للطابور،  ينادى التابع <code>failed</code> من المنصت. يتلقى التابع <code>failed</code> نسخة من الاستثناء الذي سبب الفشل:<syntaxhighlight lang="php">
 
+
<?php
 
namespace App\Listeners;
 
namespace App\Listeners;
  
 
use App\Events\OrderShipped;
 
use App\Events\OrderShipped;
 
 
use Illuminate\Queue\InteractsWithQueue;
 
use Illuminate\Queue\InteractsWithQueue;
 
 
use Illuminate\Contracts\Queue\ShouldQueue;
 
use Illuminate\Contracts\Queue\ShouldQueue;
  
 
class SendShipmentNotification implements ShouldQueue
 
class SendShipmentNotification implements ShouldQueue
 
 
{
 
{
  
سطر 286: سطر 235:
  
 
   /**
 
   /**
 
 
    * معالجة الحدث
 
    * معالجة الحدث
 
 
    *
 
    *
 
 
    * @param  \App\Events\OrderShipped  $event
 
    * @param  \App\Events\OrderShipped  $event
 
 
    * @return void
 
    * @return void
 
 
    */
 
    */
  
سطر 300: سطر 244:
  
 
   {
 
   {
 
 
      //
 
      //
 
 
   }
 
   }
  
 
   /**
 
   /**
 
 
    * معالجة العمل الفاشل
 
    * معالجة العمل الفاشل
 
 
    *
 
    *
 
 
    * @param  \App\Events\OrderShipped  $event
 
    * @param  \App\Events\OrderShipped  $event
 
 
    * @param  \Exception  $exception
 
    * @param  \Exception  $exception
 
 
    * @return void
 
    * @return void
 
 
    */
 
    */
  
سطر 322: سطر 258:
  
 
   {
 
   {
 
 
      //
 
      //
 +
   }
 +
}
  
   }
 
  
}
+
</syntaxhighlight>
  
 
== إرسال الأحداث ==
 
== إرسال الأحداث ==
لإرسال حدث، مرّر  نسخة منه للمساعد event. سيُطلق المساعد لكل المنصتات المسجّلة. حيث أنّ المساعد عامّ يمكن استخدامه من كامل التطبيق:
+
لإرسال حدث، مرّر  نسخة منه للمساعد <code>event</code>. سيُطلق المساعد لكل المنصتات المسجّلة. حيث أنّ المساعد عامّ يمكن استخدامه من كامل التطبيق:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
  
سطر 337: سطر 272:
  
 
use App\Order;
 
use App\Order;
 
 
use App\Events\OrderShipped;
 
use App\Events\OrderShipped;
 
 
use App\Http\Controllers\Controller;
 
use App\Http\Controllers\Controller;
  
سطر 347: سطر 280:
  
 
   /**
 
   /**
 
 
    * تحميل طلب معين.
 
    * تحميل طلب معين.
 
 
    *
 
    *
 
+
    * @param  int $orderId
    * @param  int $orderId
 
 
 
 
    * @return Response
 
    * @return Response
 
 
    */
 
    */
  
سطر 361: سطر 289:
  
 
   {
 
   {
 
 
       $order = Order::findOrFail($orderId);
 
       $order = Order::findOrFail($orderId);
  
سطر 369: سطر 296:
  
 
   }
 
   }
 +
}
 +
  
}
+
</syntaxhighlight>
  
 
ملاحظة : عند الاختبار، من المفيد التأكد من إطلاق الأحداث دون تشغيل منصتاتها. مساعدات الاختبار المضمّنة في Laravel تجعل هذا ممكنًا.
 
ملاحظة : عند الاختبار، من المفيد التأكد من إطلاق الأحداث دون تشغيل منصتاتها. مساعدات الاختبار المضمّنة في Laravel تجعل هذا ممكنًا.
سطر 377: سطر 306:
  
 
=== كتابة مشتركات الأحداث ===
 
=== كتابة مشتركات الأحداث ===
مشتركات الأحداث هي أصناف يمكنها الاشتراك في أحداث عديدة من داخل الصنف نفسه. مما يسمح بتعريف عدّة معالجات (handlers) في صنف واحد. يجب على المشتركات تعريف التابع subscribe، الذي يقبل نسخة من مطلق الأحداث. يمكن نداء call مع مطلق أحداث معين لتسجيل منصتات الحدث:
+
مشتركات الأحداث هي أصناف يمكنها الاشتراك في أحداث عديدة من داخل الصنف نفسه. مما يسمح بتعريف عدّة معالجات (handlers) في صنف واحد. يجب على المشتركات تعريف التابع <code>subscribe</code>، الذي يقبل نسخة من مطلق الأحداث. يمكن نداء call مع مطلق أحداث معين لتسجيل منصتات الحدث:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
  
سطر 384: سطر 312:
  
 
class UserEventSubscriber
 
class UserEventSubscriber
 
 
{
 
{
  
 
   /**
 
   /**
 
 
    * معالجة أحداث تسجيل دخول المستخدم     */
 
    * معالجة أحداث تسجيل دخول المستخدم     */
  
سطر 394: سطر 320:
  
 
   /**
 
   /**
 
 
    * معالجة أحداث تسجيل خروج المستخدم     */
 
    * معالجة أحداث تسجيل خروج المستخدم     */
  
سطر 400: سطر 325:
  
 
   /**
 
   /**
 
 
    * تسجيل المنصتات للمشترك
 
    * تسجيل المنصتات للمشترك
 
 
    *
 
    *
 
 
    * @param  \Illuminate\Events\Dispatcher  $events
 
    * @param  \Illuminate\Events\Dispatcher  $events
 
 
    */
 
    */
  
 
   public function subscribe($events)
 
   public function subscribe($events)
 
 
   {
 
   {
 
 
       $events->listen(
 
       $events->listen(
  
 
           'Illuminate\Auth\Events\Login',
 
           'Illuminate\Auth\Events\Login',
 
 
           'App\Listeners\UserEventSubscriber@onUserLogin'
 
           'App\Listeners\UserEventSubscriber@onUserLogin'
 
 
       );
 
       );
  
سطر 424: سطر 341:
  
 
           'Illuminate\Auth\Events\Logout',
 
           'Illuminate\Auth\Events\Logout',
 
 
           'App\Listeners\UserEventSubscriber@onUserLogout'
 
           'App\Listeners\UserEventSubscriber@onUserLogout'
 
 
       );
 
       );
 
 
   }
 
   }
  
 
}
 
}
 +
 +
 +
</syntaxhighlight>
  
 
=== تسجيل مشتركات الأحداث ===
 
=== تسجيل مشتركات الأحداث ===
بعد كتابة المشتركات، أنت جاهز لتسجيلها في مطلق الأحداث. يتم التسجيل باستعمال الخاصية subscribe$ من EventServiceProvider. مثلا، لنضف UserEventSubscriber للقائمة:
+
بعد كتابة المشتركات، أنت جاهز لتسجيلها في مطلق الأحداث. يتم التسجيل باستعمال الخاصية <code>subscribe$</code> من EventServiceProvider. مثلا، لنضف <code>UserEventSubscriber</code> للقائمة:<syntaxhighlight lang="php">
 
 
 
<?php
 
<?php
  
سطر 443: سطر 359:
  
 
class EventServiceProvider extends ServiceProvider
 
class EventServiceProvider extends ServiceProvider
 
 
{
 
{
  
 
   /**
 
   /**
 
 
    * عمليات ربط منصت الحدث
 
    * عمليات ربط منصت الحدث
 
 
    *
 
    *
 
 
    * @var array
 
    * @var array
 
 
    */
 
    */
  
سطر 459: سطر 370:
  
 
      //
 
      //
 
 
   ];
 
   ];
  
 
   /**
 
   /**
 
 
    *صنف المشترك للتسجيل
 
    *صنف المشترك للتسجيل
 
 
    *
 
    *
 
 
    * @var array
 
    * @var array
 
 
    */
 
    */
  
سطر 477: سطر 383:
  
 
   ];
 
   ];
 +
}
 +
  
}
+
</syntaxhighlight>
  
 
== مصادر ==
 
== مصادر ==
* صفحة Events من توثيق Laravel الرسمي.
+
* [https://laravel.com/docs/5.6/events صفحة Events من توثيق Laravel الرسمي.]

المراجعة الحالية بتاريخ 14:06، 24 أكتوبر 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 نسخة من الاستثناء الذي سبب الفشل:

<?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)

   {
      //
   }

   /**
    * معالجة العمل الفاشل
    *
    * @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',

   ];
}

مصادر