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

من موسوعة حسوب
لا ملخص تعديل
لا ملخص تعديل
 
(6 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:}}</noinclude>
<noinclude>{{DISPLAYTITLE:البث (Broadcasting) في Laravel}}</noinclude>
=== المقدمة ===
== مقدمة ==
في العديد من التطبيقات الحديثة، تُستعمل Websockets لتنفيذ واجهات استخدام فورية ذات تحيين مباشر. عند رفع بعض البيانات للخادم، تُرسَل في العادة رسالة على اتصال websocket لتُعالَج من قبل العميل. يوفّر هذا بديلًا فعالًا للسحب المتواصل للتطبيق من أجل التغييرات.
في العديد من التطبيقات الحديثة، تُستعمل Websockets لتنفيذ واجهات استخدام فورية ذات تحيين مباشر. عند رفع بعض البيانات للخادم، تُرسَل في العادة رسالة على اتصال websocket لتُعالَج من قبل العميل. يوفّر هذا بديلًا فعالًا للسحب المتواصل للتطبيق من أجل التغييرات.
لمساعدتك في بناء هذا النوع من التطبيقات، يجعل [[Laravel]] من السهل "بث" أحداث عبر صلة websocket. يسمح بث الأحداث بمشاركة نفس الأحداث بين شيفرة من جهة الخادم وشيفرة من جهة العميل.
لمساعدتك في بناء هذا النوع من التطبيقات، يجعل [[Laravel]] من السهل "بث" أحداث عبر صلة websocket. يسمح بث الأحداث بمشاركة نفس الأحداث بين شيفرة من جهة الخادم وشيفرة من جهة العميل.
سطر 6: سطر 6:
<u>ملاحظة</u>: قبل التعمق في بث الأحداث، تأكد من قراءة [[Laravel/events|توثيق Laravel الخاص بالأحداث والمستمعات]].
<u>ملاحظة</u>: قبل التعمق في بث الأحداث، تأكد من قراءة [[Laravel/events|توثيق Laravel الخاص بالأحداث والمستمعات]].


==== الضبط ====
=== الضبط ===
تُخزّن كل خيارات ضبط البث في الملف <code>config/broadcast.php</code>. يدعم [[Laravel]] برامج تشغيل بث عديدة من البداية مثل Pusher و Redis والمشغل المحلي log للبرمجة والإصلاح. وتتوافر أيضًا القيمة <code>null</code> مما يسمح بالتعطيل الكامل لعملية البث. يوجد مثال ضبط لكل هذه المشغلات في الملف <code>config/broadcast.php</code>.
تُخزّن كل خيارات ضبط البث في الملف <code>config/broadcast.php</code>. يدعم [[Laravel]] برامج تشغيل بث عديدة من البداية مثل Pusher و Redis والمشغل المحلي log للبرمجة والإصلاح. وتتوافر أيضًا القيمة <code>null</code> مما يسمح بالتعطيل الكامل لعملية البث. يوجد مثال ضبط لكل هذه المشغلات في الملف <code>config/broadcast.php</code>.


===== مزودو خدمات البث =====
==== مزودو خدمات البث ====
قبل بث أي حدث، يجب عليك أولا تسجيله في الملف <code>App\Providers\BroadcastServiceProvider</code>. في التطبيقات الجديدة، ستحتاج إلى إلغاء التعليق في مصفوفة <code>providers</code> من الملف <code>config/app.php</code>. سيسمح هذا المزود بتسجيل مسارات الترخيص والنداءات.
قبل بث أي حدث، يجب عليك أولا تسجيله في الملف <code>App\Providers\BroadcastServiceProvider</code>. في التطبيقات الجديدة، ستحتاج إلى إلغاء التعليق في مصفوفة <code>providers</code> من الملف <code>config/app.php</code>. سيسمح هذا المزود بتسجيل مسارات الترخيص والنداءات.


===== الرمز المميز CSRF =====
==== الرمز المميز CSRF ====
يحتاج Laravel Echo الولوج لرموز CSRF للدورة الحالية. يجب أن تتأكد من أنّ العنصر <code><head></code> في [[HTML]] يعرف العنصر <code><meta></code> الذي يحتوي على الرمز CSRF:<syntaxhighlight lang="php">
يحتاج Laravel Echo الولوج لرموز CSRF للدورة الحالية. يجب أن تتأكد من أنّ العنصر <code><head></code> في [[HTML]] يعرف العنصر <code><meta></code> الذي يحتوي على الرمز CSRF:<syntaxhighlight lang="php">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="csrf-token" content="{{ csrf_token() }}">
</syntaxhighlight>
</syntaxhighlight>


==== متطلبات المشغّل ====
=== متطلبات المشغّل ===


===== Pusher =====
==== Pusher ====
إذا كنت تبث الأحداث باستخدام Pusher، فيجب عليك تثبيت Pusher PHP SDK باستعمال منظم الحزم Composer:
إذا كنت تبث الأحداث باستخدام Pusher، فيجب عليك تثبيت Pusher PHP SDK باستعمال منظم الحزم Composer:
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
سطر 51: سطر 51:
</syntaxhighlight>
</syntaxhighlight>


===== Redis =====
==== Redis ====
إذا كنت تستعمل الباث Redis، يجب عليك تثبيت المكتبة Predis:<syntaxhighlight lang="php">
إذا كنت تستعمل الباث Redis، يجب عليك تثبيت المكتبة Predis:<syntaxhighlight lang="php">
composer require predis/predis
composer require predis/predis
سطر 60: سطر 60:
عندما يبث Redis حدثًا، فسيُنشر على القناة المخصصة للحدث وسيحمل سلسلة محارف مشفرة بطريقة [[JSON]] تتضمن اسم الحدث ومعلومات <code>data</code> ومعرف المستخدم الذي صنع التوصيل socket (إن أمكن).
عندما يبث Redis حدثًا، فسيُنشر على القناة المخصصة للحدث وسيحمل سلسلة محارف مشفرة بطريقة [[JSON]] تتضمن اسم الحدث ومعلومات <code>data</code> ومعرف المستخدم الذي صنع التوصيل socket (إن أمكن).


===== Socket.io =====
==== Socket.io ====
إذا كنت ستضيف Socket.io للباث Redis، ستحتاج لإضافة مكتبة عميل [[JavaScript]] للتطبيق. يمكنك تثبيته عبر منظم الخدمات NPM:<syntaxhighlight lang="php">
إذا كنت ستضيف Socket.io للباث Redis، ستحتاج لإضافة مكتبة عميل [[JavaScript]] للتطبيق. يمكنك تثبيته عبر منظم الخدمات NPM:<syntaxhighlight lang="php">
npm install --save socket.io-client
npm install --save socket.io-client
سطر 81: سطر 81:
أخيرا، عليك تشغيل خادم Socket.io متوافق. لا يتضمن [[Laravel]] خادم socket.io لكن هنالك خادمٌ يتكفل به المجتمع موجودٌ في github في المستودع [https://github.com/tlaverdure/laravel-echo-server tlaverdure/laravel-echo-server].
أخيرا، عليك تشغيل خادم Socket.io متوافق. لا يتضمن [[Laravel]] خادم socket.io لكن هنالك خادمٌ يتكفل به المجتمع موجودٌ في github في المستودع [https://github.com/tlaverdure/laravel-echo-server tlaverdure/laravel-echo-server].


===== متطلبات قائمات الإنتظار =====
==== متطلبات طوابير الانتظار ====
قبل بث الأحداث, ستحتاج لضبط و تشغيل مستمعي قائمات الإنتظار. يتم البث عن طريق مهمات موجودة في قائمات انتظار حتى لا يتأثر وقت اجابة التطبيق.
قبل بث الأحداث, ستحتاج لضبط و تشغيل مستمعي طوابير الانتظار. يتم البث عن طريق مهمات موجودة في قائمات انتظار حتى لا يتأثر وقت اجابة التطبيق.


=== نظرة عامة على المفهوم ===
== نظرة عامة على مفهوم البث ==
يسمح بث الأحداث في [[Laravel]] ببث أحداث من جهة الخادم إلى سكربات [[JavaScript]] التابعة لتطبيقك من جهة العميل باستخدام مقاربة مبنية على المشغلات في Websockets.
يسمح بث الأحداث في [[Laravel]] ببث أحداث من جهة الخادم إلى سكربات [[JavaScript]] التابعة لتطبيقك من جهة العميل باستخدام مقاربة مبنية على المشغلات في Websockets.


تبث الأحداث في قنوات "channels" قد تكون عامة أو خاصة. يمكن لأي مستخدم للتطبيق أن ينخرط في قناة عامة دون الحاجة لترخيص أو استيثاق. لكن للاستماع على قناة خاصة لا بد من الاستيثاق والترخيص.
تبث الأحداث في قنوات "channels" قد تكون عامة أو خاصة. يمكن لأي مستخدم للتطبيق أن ينخرط في قناة عامة دون الحاجة لترخيص أو استيثاق. لكن للاستماع على قناة خاصة لا بد من الاستيثاق والترخيص.


==== استخدام تطبيق مثال ====
=== استخدام تطبيق مثال ===
قبل التعمق في كل مكون من بث الأحداث، لنأخذ نظرة عامة على تطبيق تسوق إلكتروني على سبيل المثال. لن ندقق في ضبط Pusher أو Laravel Echo لأن ذلك مذكور في أقسام أخرى من التوثيق.
قبل التعمق في كل مكون من بث الأحداث، لنأخذ نظرة عامة على تطبيق تسوق إلكتروني على سبيل المثال. لن ندقق في ضبط Pusher أو Laravel Echo لأن ذلك مذكور في أقسام أخرى من التوثيق.


سطر 98: سطر 98:
</syntaxhighlight>
</syntaxhighlight>


===== الواجهة ShouldBroadcast =====
==== الواجهة ShouldBroadcast ====
عندما يطّلع المستخدم على أحد طلباته، لا نريده أن يُحدّث الصفحة ليرى تحيين الحالة. بل نريد بث تحديثات التطبيق عند إنشائها. لذا يجب إضافة الواجهة <code>ShouldBroadcast</code> للحدث <code>ShippingStatusUpdated</code>. مما سيخبر  Laravel أن يبث الحدث عند إطلاقه:<syntaxhighlight lang="php">
عندما يطّلع المستخدم على أحد طلباته، لا نريده أن يُحدّث الصفحة ليرى تحيين الحالة. بل نريد بث تحديثات التطبيق عند إنشائها. لذا يجب إضافة الواجهة <code>ShouldBroadcast</code> للحدث <code>ShippingStatusUpdated</code>. مما سيخبر  Laravel أن يبث الحدث عند إطلاقه:<syntaxhighlight lang="php">
<?php
<?php
سطر 144: سطر 144:
</syntaxhighlight>
</syntaxhighlight>


===== ترخيص القنوات =====
==== ترخيص القنوات ====
تذكر انّ المستخدم يجب أن يسجل الدخول ليستمع للقنوات الخاصة. يمكن تعريف قواعد تراخيص القناة في <code>routes/channels.php</code>. في هذا المثال، يجب التأكد من أن المستخدم الذي يريد الاستماع على القناة الخاصة <code>order.1</code> هو صاحب الطلب:<syntaxhighlight lang="php">
تذكر انّ المستخدم يجب أن يسجل الدخول ليستمع للقنوات الخاصة. يمكن تعريف قواعد تراخيص القناة في <code>routes/channels.php</code>. في هذا المثال، يجب التأكد من أن المستخدم الذي يريد الاستماع على القناة الخاصة <code>order.1</code> هو صاحب الطلب:<syntaxhighlight lang="php">
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
سطر 157: سطر 157:
كل نداءات التراخيص تتلقى المستخدم المسجل حاليا كمعامل أول و معامل بديل عن أي معامل إضافي. في هذا المثال، نستخدم البديل <code>{orderId}</code> للإعلام أنّ القسم "ID" من اسم القناة متغير.
كل نداءات التراخيص تتلقى المستخدم المسجل حاليا كمعامل أول و معامل بديل عن أي معامل إضافي. في هذا المثال، نستخدم البديل <code>{orderId}</code> للإعلام أنّ القسم "ID" من اسم القناة متغير.


===== الإستماع لبث الحدث =====
==== الاستماع لبث الحدث ====
بعد ذلك، كل ما تبقى هو الإستماع للحدث في شيفرة <code>JavaScript</code> للتطبيق. يمكن القيام بهذا باستعمال Laravel Echo. أولًا، نستعمل التابع <code>private</code> للدخول إلى القناة الخاصة. ثم، يمكننا استعمال التابع <code>listen</code> للاستماع للحدث <code>ShippingStatusUpdated</code>. في العادة، كل الخاصيات العامة للحدث تُضمَّن في حدث البث:<syntaxhighlight lang="php">
بعد ذلك، كل ما تبقى هو الإستماع للحدث في شيفرة <code>JavaScript</code> للتطبيق. يمكن القيام بهذا باستعمال Laravel Echo. أولًا، نستعمل التابع <code>private</code> للدخول إلى القناة الخاصة. ثم، يمكننا استعمال التابع <code>listen</code> للاستماع للحدث <code>ShippingStatusUpdated</code>. في العادة، كل الخاصيات العامة للحدث تُضمَّن في حدث البث:<syntaxhighlight lang="php">
Echo.private(`order.${orderId}`)
Echo.private(`order.${orderId}`)
سطر 167: سطر 167:
</syntaxhighlight>
</syntaxhighlight>


=== تعريف أحداث البث ===
== تعريف أحداث البث ==
لإعلام [[Laravel]] أن حدثا ما يجب بثّه، نفذ الواجهة<code>Illuminate\Contracts\Broadcasting\ShouldBroadcast</code> في صنف الحدث. تُحمَّل هذه الواجهة في كل أصناف الأحداث لذا يمكنك إضافتها بسهولة لأي حدث.
لإعلام [[Laravel]] أن حدثا ما يجب بثّه، نفذ الواجهة<code>Illuminate\Contracts\Broadcasting\ShouldBroadcast</code> في صنف الحدث. تُحمَّل هذه الواجهة في كل أصناف الأحداث لذا يمكنك إضافتها بسهولة لأي حدث.
تتطلب الواجهة <code>ShouldBroadcast</code> كتابة تابع وحيد هو <code>broadcastOn</code>. يعيد هذا التابع قناة أو مصفوفة قنوات يبث عليها الحدث. يجب أن تكون القناة نسخة <code>Channel</code> أو <code>PrivateChannel</code> أو <code>PresenceChannel</code>. تمثل نسخة <code>Channel</code> القنوات العامة التي يمكن لأي مستخدم الدخول فيها في حين <code>PrivateChannel</code> و <code>PresenceChannel</code> تمثل قنوات تتطلب ترخيصًا:<syntaxhighlight lang="php">
تتطلب الواجهة <code>ShouldBroadcast</code> كتابة تابع وحيد هو <code>broadcastOn</code>. يعيد هذا التابع قناة أو مصفوفة قنوات يبث عليها الحدث. يجب أن تكون القناة نسخة <code>Channel</code> أو <code>PrivateChannel</code> أو <code>PresenceChannel</code>. تمثل نسخة <code>Channel</code> القنوات العامة التي يمكن لأي مستخدم الدخول فيها في حين <code>PrivateChannel</code> و <code>PresenceChannel</code> تمثل قنوات تتطلب ترخيصًا:<syntaxhighlight lang="php">
سطر 205: سطر 205:
ثم عليك إطلاق حدث كما تفعل عادة. عند إطلاق الحدث، تبث مهمة في قائمة الإنتظار آليًا الحدث على المشغل الذي اخترته.
ثم عليك إطلاق حدث كما تفعل عادة. عند إطلاق الحدث، تبث مهمة في قائمة الإنتظار آليًا الحدث على المشغل الذي اخترته.


==== اسم البث ====
=== اسم البث ===
في العادة، يبث [[Laravel]] الأحداث باستخدام أسماء أصناف الأحداث. لكن بإمكانك تخصيص اسم البث عبر تعريف التابع <code>broadcastAs</code> في الحدث:<syntaxhighlight lang="php">
في العادة، يبث [[Laravel]] الأحداث باستخدام أسماء أصناف الأحداث. لكن بإمكانك تخصيص اسم البث عبر تعريف التابع <code>broadcastAs</code> في الحدث:<syntaxhighlight lang="php">
/**
/**
سطر 230: سطر 230:
</syntaxhighlight>
</syntaxhighlight>


==== بيانات البث ====
=== بيانات البث ===
عند بث حدث، تتم سلسلة كل خاصياته العامة آليًا كتحميل للحدث، مما يسمح لك بالولوج لكل بياناته العامة من تطبيق [[JavaScript]]. لذا لو كان للحدث خاصية واحدة <code>user$</code> مثلًا تحتوي على نموذج [[Laravel/eloquent|Eloquent]]، يكون نحميل البث كما يلي:
عند بث حدث، تتم سلسلة كل خاصياته العامة آليًا كتحميل للحدث، مما يسمح لك بالولوج لكل بياناته العامة من تطبيق [[JavaScript]]. لذا لو كان للحدث خاصية واحدة <code>user$</code> مثلًا تحتوي على نموذج [[Laravel/eloquent|Eloquent]]، يكون نحميل البث كما يلي:
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
سطر 260: سطر 260:
</syntaxhighlight>
</syntaxhighlight>


==== قائمة انتظار البث ====
=== طابور انتظار البث ===
في العادة، يوضع كل أحداث البث في قائمة الإنتظار الأولية للصلة الأولية المعرّفة في ملف الضبط <code>queue.php</code>. يمكنك تخصيص قائمة انتظار البث عبر تعريف الخاصية <code>broadcastQueue</code> في صنف الحدث. يجب أن تحدد هذه الخاصية اسم قائمة الانتظار التي تود استعمالها عند البث:<syntaxhighlight lang="php">
في العادة، يوضع كل أحداث البث في طابور الانتظار الأولية للصلة الأولية المعرّفة في ملف الضبط <code>queue.php</code>. يمكنك تخصيص طابور انتظار البث عبر تعريف الخاصية <code>broadcastQueue</code> في صنف الحدث. يجب أن تحدد هذه الخاصية اسم طابور الانتظار الذي تود استعماله عند البث:<syntaxhighlight lang="php">
/**
/**


سطر 273: سطر 273:
</syntaxhighlight>
</syntaxhighlight>


إذا أردت بث الأحداث باستعمال قائمة الإنتظار <code>sync</code> بدل المشغل العادي، يمكنك تنفيذ <code>shouldBroadcastNow</code> بدل <code>ShouldBoradcast</code>:
إذا أردت بث الأحداث باستعمال طابور  الانتظار <code>sync</code> بدل المشغل العادي، يمكنك تنفيذ <code>shouldBroadcastNow</code> بدل <code>ShouldBoradcast</code>:
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
<?php
<?php
سطر 289: سطر 289:
</syntaxhighlight>
</syntaxhighlight>


==== شروط البث ====
=== شروط البث ===
في بعض الأحيان، قد تريد بث الأحداث فقط إن تحقق شرط معين. يمكنك تحديد هذه الشروط عبر إضافة التابع <code>broadcastWhen</code> لصنف الحدث:<syntaxhighlight lang="php">
في بعض الأحيان، قد تريد بث الأحداث فقط إن تحقق شرط معين. يمكنك تحديد هذه الشروط عبر إضافة التابع <code>broadcastWhen</code> لصنف الحدث:<syntaxhighlight lang="php">
/**
/**
سطر 305: سطر 305:
</syntaxhighlight>
</syntaxhighlight>


=== الترخيص للقنوات ===
== الترخيص للقنوات ==
تتطلب القنوات الخاصة ترخيصًا ليتمكن المستخدم المسجل حاليًا من الإستماع إليها. يتم هذا عبر إطلاق طلب HTTP للتطبيق باسم القناة وجعل التطبيق يقرر هل يسمح للمستخدم بالإستماع أم لا. عند استخدام Laravel Echo، يُصنع طلب HTTP للترخيص بالإنخراط في القنوات الخاصة تلقائيًا. لكن عليك تعريف المسار للإجابة على الطلب.
تتطلب القنوات الخاصة ترخيصًا ليتمكن المستخدم المسجل حاليًا من الإستماع إليها. يتم هذا عبر إطلاق طلب HTTP للتطبيق باسم القناة وجعل التطبيق يقرر هل يسمح للمستخدم بالإستماع أم لا. عند استخدام Laravel Echo، يُصنع طلب HTTP للترخيص بالإنخراط في القنوات الخاصة تلقائيًا. لكن عليك تعريف المسار للإجابة على الطلب.


==== تعريف مسارات الترخيص ====
=== تعريف مسارات الترخيص ===
من حسن الحظ، يجعل Laravel تعريف المسارات لإجابة طلبات الترخيص أمرًا سهلًا. في مزود الخدمات <code>BroadcastServiceProvider</code> المضمن في تطبيق [[Laravel]]، سترى نداء للتابع <code>Broadcast::routes</code>. سيسجل هذا التابع المسار <code>broadcasting/auth</code> لمعالجة طلبات الترخيص.<syntaxhighlight lang="php">
من حسن الحظ، يجعل Laravel تعريف المسارات لإجابة طلبات الترخيص أمرًا سهلًا. في مزود الخدمات <code>BroadcastServiceProvider</code> المضمن في تطبيق [[Laravel]]، سترى نداء للتابع <code>Broadcast::routes</code>. سيسجل هذا التابع المسار <code>broadcasting/auth</code> لمعالجة طلبات الترخيص.<syntaxhighlight lang="php">
Broadcast::routes();
Broadcast::routes();
سطر 317: سطر 317:
</syntaxhighlight>
</syntaxhighlight>


==== تعريف نداءات الترخيص ====
=== تعريف نداءات الترخيص ===
بعد ذلك، نحتاج لتعريف التحكم المنطقي الذي سيقوم بالترخيص. يتم هذا في الملف <code>routes/channels.php</code> في التطبيق. في هذا الملف، يمكنك استخدام التابع <code>Broadcast::channel</code> لتسجيل نداءات ترخيص القنوات:<syntaxhighlight lang="php">
بعد ذلك، نحتاج لتعريف التحكم المنطقي الذي سيقوم بالترخيص. يتم هذا في الملف <code>routes/channels.php</code> في التطبيق. في هذا الملف، يمكنك استخدام التابع <code>Broadcast::channel</code> لتسجيل نداءات ترخيص القنوات:<syntaxhighlight lang="php">
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
سطر 330: سطر 330:
كل نداءات التراخيص تتلقى المستخدم المسجل حاليًا كمعامل أول و معامل بديل عن أي معامل إضافي. في المثال السابق، نستخدم البديل <code>{orderId}</code> للإعلام أنّ القسم "<code>ID</code>" من اسم القناة متغير.
كل نداءات التراخيص تتلقى المستخدم المسجل حاليًا كمعامل أول و معامل بديل عن أي معامل إضافي. في المثال السابق، نستخدم البديل <code>{orderId}</code> للإعلام أنّ القسم "<code>ID</code>" من اسم القناة متغير.


===== ترخيص نداءات ربط النماذج =====
==== ترخيص نداءات ربط النماذج ====
مثل مسارات HTTP، تستفيد مسارات القنوات من ربط النماذج المباشر و غير المباشر. مثلًا، بدل تلقي سلسلة محارف أو معرّف رقمي، يمكن أن تطلب نسخة من <code>Order</code>:
مثل مسارات HTTP، تستفيد مسارات القنوات من ربط النماذج المباشر و غير المباشر. مثلًا، بدل تلقي سلسلة محارف أو معرّف رقمي، يمكن أن تطلب نسخة من <code>Order</code>:
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
سطر 343: سطر 343:
</syntaxhighlight>
</syntaxhighlight>


==== تعريف أصناف القنوات ====
=== تعريف أصناف القنوات ===
إذا كان التطبيق يستعمل العديد من القنوات، سيصبح الملف <code>routes/channels.php</code> ضخمًا. لذا، بدل استعمال <code>Closure</code> لترخيص القنوات، يمكن استعمال أصناف للقنوات. لإنشاء أصناف القنوات، استعمل الأمر <code>make:channel</code>. سيضع الأمر الأصناف المصنوعة في المجلد <code>App/Broadcasting</code><syntaxhighlight lang="php">
إذا كان التطبيق يستعمل العديد من القنوات، سيصبح الملف <code>routes/channels.php</code> ضخمًا. لذا، بدل استعمال <code>Closure</code> لترخيص القنوات، يمكن استعمال أصناف للقنوات. لإنشاء أصناف القنوات، استعمل الأمر <code>make:channel</code>. سيضع الأمر الأصناف المصنوعة في المجلد <code>App/Broadcasting</code><syntaxhighlight lang="php">
php artisan make:channel OrderChannel
php artisan make:channel OrderChannel
سطر 392: سطر 392:
<u>ملاحظة</u>: كالعديد من الأصناف في [[Laravel]]، تُعالج أصناف القنوات في حاوي الخدمات. لذا يمكنك التلميح إلى نوع الإعتماديات التي تحتاج لها القناة في باني الصنف التي يحتاجها باني الصنف.
<u>ملاحظة</u>: كالعديد من الأصناف في [[Laravel]]، تُعالج أصناف القنوات في حاوي الخدمات. لذا يمكنك التلميح إلى نوع الإعتماديات التي تحتاج لها القناة في باني الصنف التي يحتاجها باني الصنف.


=== بث الأحداث ===
== بث الأحداث ==
بعد تعريف الحدث وإضافة الواجهة <code>ShouldBroadcast</code>، تحتاج فقط لإطلاق الحدث باستعمال الدالة <code>event</code>. سيُلاحظ مُطلِق الأحداث أن الحدث تم ترميزه بالواجهة <code>ShouldBroadcast</code> ويضيفه لقائمة انتظار البث:<syntaxhighlight lang="php">
بعد تعريف الحدث وإضافة الواجهة <code>ShouldBroadcast</code>، تحتاج فقط لإطلاق الحدث باستعمال الدالة <code>event</code>. سيُلاحظ مُطلِق الأحداث أن الحدث تم ترميزه بالواجهة <code>ShouldBroadcast</code> ويضيفه لقائمة انتظار البث:<syntaxhighlight lang="php">
event(new ShippingStatusUpdated($update));
event(new ShippingStatusUpdated($update));
</syntaxhighlight>
</syntaxhighlight>


==== فقط للآخرين ====
=== فقط للآخرين ===
عند بناء تطبيق يستعمل تقنية البث، يمكنك تعويض الدالة <code>event</code> بالدالة <code>broadcast</code>.  مثل <code>event</code>، يُطلق <code>broadcast</code> الحدث من جهة الخادم للمستمع في جهة العميل<syntaxhighlight lang="php">
عند بناء تطبيق يستعمل تقنية البث، يمكنك تعويض الدالة <code>event</code> بالدالة <code>broadcast</code>.  مثل <code>event</code>، يُطلق <code>broadcast</code> الحدث من جهة الخادم للمستمع في جهة العميل<syntaxhighlight lang="php">
broadcast(new ShippingStatusUpdated($update));
broadcast(new ShippingStatusUpdated($update));
سطر 419: سطر 419:
<u>تنبيه</u>: يجب على الحدث استخدام الخاصية <code>Illuminate\Broadcasting\InteractsWithSockets</code> للاستعمال التابع <code>toOthers</code>.
<u>تنبيه</u>: يجب على الحدث استخدام الخاصية <code>Illuminate\Broadcasting\InteractsWithSockets</code> للاستعمال التابع <code>toOthers</code>.


===== الضبط =====
==== الضبط ====
عند بدء مثيل Laravel Echo، يُعطى معرّف توصيل (Socket id) للصلة. إذا كنت تستخدم Vue و Axios، يُرفق المعرّف تلقائيًا بكل طلب خارج كعنوان <code>x-socket-ID</code>. ثم عندما تنادي التابع <code>toOthers</code>، يأخذ Laravel المعرّف من العنوان ويأمر الباث بعدن البث لأي صلة تحمل ذلك المعرّف.
عند بدء مثيل Laravel Echo، يُعطى معرّف توصيل (Socket id) للصلة. إذا كنت تستخدم Vue و Axios، يُرفق المعرّف تلقائيًا بكل طلب خارج كعنوان <code>x-socket-ID</code>. ثم عندما تنادي التابع <code>toOthers</code>، يأخذ Laravel المعرّف من العنوان ويأمر الباث بعدن البث لأي صلة تحمل ذلك المعرّف.


سطر 427: سطر 427:
</syntaxhighlight>
</syntaxhighlight>


=== تلقي البث ===
== تلقي البث ==


==== تثبيت Laravel echo ====
=== تثبيت Laravel echo ===
Laravel Echo هي مكتبة [[JavaScript|Javascript]] تجعل الانخراط في قناة و والإستماع للأحداث أمرًا سهلًا. يمكنك تثبيت Echo عبر منظم الحزم NPM. في هذا المثال، سنثبت أيضًا <code>pusher-js</code> حيث سنستخدم المشغل pusher للبث:<syntaxhighlight lang="php">
Laravel Echo هي مكتبة [[JavaScript|Javascript]] تجعل الانخراط في قناة و والإستماع للأحداث أمرًا سهلًا. يمكنك تثبيت Echo عبر منظم الحزم NPM. في هذا المثال، سنثبت أيضًا <code>pusher-js</code> حيث سنستخدم المشغل pusher للبث:<syntaxhighlight lang="php">
npm install --save laravel-echo pusher-js
npm install --save laravel-echo pusher-js
سطر 458: سطر 458:
</syntaxhighlight>
</syntaxhighlight>


==== الإستماع للأحداث ====
=== الاستماع للأحداث ===
بعد تثبيت Echo و تشغيله، أنت الآن جاهز للاستماع للأحداث. أولًا، استخدم التابع <code>channel</code> لإعادة نسخة من القناة، ثم استدع التابع <code>listen</code> لحدث معين:<syntaxhighlight lang="php">
بعد تثبيت Echo و تشغيله، أنت الآن جاهز للاستماع للأحداث. أولًا، استخدم التابع <code>channel</code> لإعادة نسخة من القناة، ثم استدع التابع <code>listen</code> لحدث معين:<syntaxhighlight lang="php">
Echo.channel('orders')
Echo.channel('orders')
سطر 477: سطر 477:
</syntaxhighlight>
</syntaxhighlight>


==== مغادرة قناة ====
=== مغادرة قناة ===
لمغادرة قناة، ينكنك نداء التابع <code>leave</code> في نسخة Echo:<syntaxhighlight lang="php">
لمغادرة قناة، ينكنك نداء التابع <code>leave</code> في نسخة Echo:<syntaxhighlight lang="php">
Echo.leave('orders');
Echo.leave('orders');
</syntaxhighlight>
</syntaxhighlight>


==== مساحة الإسم ====
=== مجالات الأسماء ===
قد تكون لاحظت في الأمثلة السابقة أننا لم نحدد مساحة اسم (namespace) كاملة لأصناف الأحداث. هذا لأن Echo يتوقع تلقائيا أن الأحداث موجودة في مجال الأسماء <code>App\Events</code>. لكن يمكنك ضبط جذر مجال الأسماء عند تشغيل Echo بتمرير خيار الضبط <code>namespace</code><syntaxhighlight lang="php">
قد تكون لاحظت في الأمثلة السابقة أننا لم نحدد مجال اسم (namespace) كامل لأصناف الأحداث. هذا لأن Echo يتوقع تلقائيا أن الأحداث موجودة في مجال الأسماء <code>App\Events</code>. لكن يمكنك ضبط جذر مجال الأسماء عند تشغيل Echo بتمرير خيار الضبط <code>namespace</code><syntaxhighlight lang="php">
window.Echo = new Echo({
window.Echo = new Echo({


سطر 503: سطر 503:
</syntaxhighlight>
</syntaxhighlight>


=== القنوات Presence ===
== قنوات الحضور ==
تبني قنوات الحضور (presence) على أمان القنوات الخاصة في حين تستغل الخاصية الإضافية بالعلم بمن ينخرط في القناة. مما يسهل من بناء خاصيات قوية وتشاركية مثل تنبيه المستخدم حين يرى مستخدم آخر نفس الصفحة.
تبني قنوات الحضور (presence) على أمان القنوات الخاصة في حين تستغل الخاصية الإضافية بالعلم بمن ينخرط في القناة. مما يسهل من بناء خاصيات قوية وتشاركية مثل تنبيه المستخدم حين يرى مستخدم آخر نفس الصفحة.


==== ترخيص قنوات الحضور ====
=== ترخيص قنوات الحضور ===
كل قنوات الحضور قنواتٌ خاصةٌ، لذا، يجب الترخيص للمستخدمين لاستعمالها. لكن عند تعريف نداء ترخيص لقناة حضور، لن تعيد <code>true</code> إذا كان المستخدم مرخصًا له بل يجب أن تعيد مصفوفة ببيانات المستخدم.
كل قنوات الحضور قنواتٌ خاصةٌ، لذا، يجب الترخيص للمستخدمين لاستعمالها. لكن عند تعريف نداء ترخيص لقناة حضور، لن تعيد <code>true</code> إذا كان المستخدم مرخصًا له بل يجب أن تعيد مصفوفة ببيانات المستخدم.
تكون البيانات الموفّرة من قبل نداء الترخيص متوفِّرة لمستمعي قنوات الحضور في تطبيق JavaScript. إذا لم يكن المستخدم مرخصًا له لدخول القناة، فيجب أن تعيد <code>false</code> أو <code>null</code>:
تكون البيانات الموفّرة من قبل نداء الترخيص متوفِّرة لمستمعي قنوات الحضور في تطبيق JavaScript. إذا لم يكن المستخدم مرخصًا له لدخول القناة، فيجب أن تعيد <code>false</code> أو <code>null</code>:
سطر 520: سطر 520:
</syntaxhighlight>
</syntaxhighlight>


==== الانضمام لقنوات الحضور ====
=== الانضمام لقنوات الحضور ===
للانضمام لقنوات الحضور، يمكنك استعمال التابع <code>join</code>. سيعيد هذا التابع تنفيذًا للتابع <code>PresenceChannel</code> الذي، بالإضافة لتوفير التابع <code>listen</code>، يسمح أيضا بالانخراط في الأحداث <code>here</code> و <code>joining</code> و <code>leaving</code>.
للانضمام لقنوات الحضور، يمكنك استعمال التابع <code>join</code>. سيعيد هذا التابع تنفيذًا للتابع <code>PresenceChannel</code> الذي، بالإضافة لتوفير التابع <code>listen</code>، يسمح أيضا بالانخراط في الأحداث <code>here</code> و <code>joining</code> و <code>leaving</code>.
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
سطر 539: سطر 539:
يُنفَّذ النداء <code>here</code> مباشرة عند الانضمام الناجح للقناة، ويتلقى مصفوفة من بيانات المستخدم لبقية المستخدمين المنخرطين في القناة. يُنفَّذ التابع <code>joining</code> عندما انضم مستخدم جديد في حين ينفَّذ التابع <code>leaving</code> عندما يغادر مستخدم القناة.
يُنفَّذ النداء <code>here</code> مباشرة عند الانضمام الناجح للقناة، ويتلقى مصفوفة من بيانات المستخدم لبقية المستخدمين المنخرطين في القناة. يُنفَّذ التابع <code>joining</code> عندما انضم مستخدم جديد في حين ينفَّذ التابع <code>leaving</code> عندما يغادر مستخدم القناة.


==== البث لقنوات الحضور ====
=== البث لقنوات الحضور ===
تتلقى قنوات الحضور أحداثًا مثل القنوات العامة أو الخاصة. باستخدام مثال غرف الرسائل، قد نريد بث الحدث <code>NewMessage</code> لقناة حضور الغرفة. للقيم بذلك، سنعيد نسخة <code>PresenceChannel</code> من التابع <code>broadcastOn</code> في الحدث:<syntaxhighlight lang="php">
تتلقى قنوات الحضور أحداثًا مثل القنوات العامة أو الخاصة. باستخدام مثال غرف الرسائل، قد نريد بث الحدث <code>NewMessage</code> لقناة حضور الغرفة. للقيم بذلك، سنعيد نسخة <code>PresenceChannel</code> من التابع <code>broadcastOn</code> في الحدث:<syntaxhighlight lang="php">
/**
/**
سطر 563: سطر 563:
</syntaxhighlight>
</syntaxhighlight>


يمكنك الإستماع لأحداث الإنضمام عبر التابع listen:
يمكنك الإستماع لأحداث الإنضمام عبر التابع <code>listen</code>:
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
Echo.join(`chat.${roomId}`)
Echo.join(`chat.${roomId}`)
سطر 576: سطر 576:
</syntaxhighlight>
</syntaxhighlight>


=== أحداث العملاء ===
== أحداث العملاء ==
<u>ملاحظة</u>: عند استعمال Pusher، عليك تفعيل الخيار "<code>Client Events</code>" في القسم "<code>App Settings</code>" من لوحة التحكم لقبول الأحداث من جهة العملاء.
'''ملاحظة''': عند استعمال Pusher، عليك تفعيل الخيار "<code>Client Events</code>" في القسم "<code>App Settings</code>" من لوحة التحكم لقبول الأحداث من جهة العملاء.


قد تريد في بعض الأحيان بث حدث لبقية المستخدمين دون المرور بتطبيق Laravel. يكون هذا مفيدًا في حالات مثل تنبيهات الكتابة، أين يمكنك أن تُعلم المستخدم أنّ مستخدمًا آخر بصدد الكتابة في شاشة معينة.
قد تريد في بعض الأحيان بث حدث لبقية المستخدمين دون المرور بتطبيق Laravel. يكون هذا مفيدًا في حالات مثل تنبيهات الكتابة، أين يمكنك أن تُعلم المستخدم أنّ مستخدمًا آخر بصدد الكتابة في شاشة معينة.
سطر 590: سطر 590:


</syntaxhighlight>
</syntaxhighlight>
للاستماع لأحداث العملاء، استخدم التابع listenForWhisper:
للاستماع لأحداث العملاء، استخدم التابع <code>listenForWhisper</code>:<syntaxhighlight lang="php">
Echo.private('chat')
Echo.private('chat')
     .listenForWhisper('typing', (e) => {
     .listenForWhisper('typing', (e) => {
         console.log(e.name);
         console.log(e.name);
     });
     });
</syntaxhighlight>


=== التنبيهات ===
== الإشعارات ==
عبر إرفاق بث الأحداث بتنبيهات، يتلقى تطبيق JavaScript التنبيهات حين تصل دون الحاجة لتحديث الصفحة. أولا، تأكد من الاطلاع على توثيق التنبيهات.
عبر إرفاق بث الأحداث بالإشعارات، يتلقى تطبيق [[JavaScript]] الإشعارات حين تصل دون الحاجة لتحديث الصفحة. أولا، تأكد من الاطلاع على [[Laravel/notifications|توثيق الإشعارات]].
بعد ضبط التنبيهات لاستخدام قنوات البث، يمكنك الإستماع للأحداث باستعمال التابع <code>notification</code>. تذكر أن اسم القناة يجب أن يوافق اسم صنف الكائن المتلقي للتنبيه<syntaxhighlight lang="php">
بعد ضبط التنبيهات لاستخدام قنوات البث، يمكنك الإستماع للأحداث باستعمال التابع <code>notification</code>. تذكر أن اسم القناة يجب أن يوافق اسم صنف الكائن المتلقي لللإشعار:<syntaxhighlight lang="php">
Echo.private(`App.User.${userId}`)
Echo.private(`App.User.${userId}`)


سطر 606: سطر 607:


</syntaxhighlight>
</syntaxhighlight>
في هذا المثال، يتلقى النداء كل التنبيهات المبعوثة إلى <code>App\User</code> عبر القناة <code>broadcast</code>. نداء ترخيص للقناة <code>App.User.{id}</code> يكون مضمنًا في مزود الخدمات <code>BroadcastServiceProvider</code> الذي يأتي مع الإطار Laravel.
في هذا المثال، يتلقى النداء كل التنبيهات المبعوثة إلى <code>App\User</code> عبر القناة <code>broadcast</code>. نداء ترخيص للقناة <code>App.User.{id}</code> يكون مضمنًا في مزود الخدمات <code>BroadcastServiceProvider</code> الذي يأتي مع الإطار [[Laravel]].


'''مصادر'''
== مصادر ==
* [https://laravel.com/docs/5.6/broadcasting صفحة Broadcasting في توثيق Laravel الرسمي.]
* [https://laravel.com/docs/5.6/broadcasting صفحة Broadcasting في توثيق Laravel الرسمي.]
[[تصنيف:Laravel]]
[[تصنيف:Laravel|{{SUBPAGENAME}}]]
[[تصنيف:Laravel Digging deeper]]
[[تصنيف:Laravel Digging deeper|{{SUBPAGENAME}}]]

المراجعة الحالية بتاريخ 14:03، 24 أكتوبر 2018

مقدمة

في العديد من التطبيقات الحديثة، تُستعمل Websockets لتنفيذ واجهات استخدام فورية ذات تحيين مباشر. عند رفع بعض البيانات للخادم، تُرسَل في العادة رسالة على اتصال websocket لتُعالَج من قبل العميل. يوفّر هذا بديلًا فعالًا للسحب المتواصل للتطبيق من أجل التغييرات. لمساعدتك في بناء هذا النوع من التطبيقات، يجعل Laravel من السهل "بث" أحداث عبر صلة websocket. يسمح بث الأحداث بمشاركة نفس الأحداث بين شيفرة من جهة الخادم وشيفرة من جهة العميل.

ملاحظة: قبل التعمق في بث الأحداث، تأكد من قراءة توثيق Laravel الخاص بالأحداث والمستمعات.

الضبط

تُخزّن كل خيارات ضبط البث في الملف config/broadcast.php. يدعم Laravel برامج تشغيل بث عديدة من البداية مثل Pusher و Redis والمشغل المحلي log للبرمجة والإصلاح. وتتوافر أيضًا القيمة null مما يسمح بالتعطيل الكامل لعملية البث. يوجد مثال ضبط لكل هذه المشغلات في الملف config/broadcast.php.

مزودو خدمات البث

قبل بث أي حدث، يجب عليك أولا تسجيله في الملف App\Providers\BroadcastServiceProvider. في التطبيقات الجديدة، ستحتاج إلى إلغاء التعليق في مصفوفة providers من الملف config/app.php. سيسمح هذا المزود بتسجيل مسارات الترخيص والنداءات.

الرمز المميز CSRF

يحتاج Laravel Echo الولوج لرموز CSRF للدورة الحالية. يجب أن تتأكد من أنّ العنصر <head> في HTML يعرف العنصر <meta> الذي يحتوي على الرمز CSRF:

<meta name="csrf-token" content="{{ csrf_token() }}">

متطلبات المشغّل

Pusher

إذا كنت تبث الأحداث باستخدام Pusher، فيجب عليك تثبيت Pusher PHP SDK باستعمال منظم الحزم Composer:

composer require pusher/pusher-php-server "~3.0"

ثم يتوجب عليك دفع اعتمادات Pusher للملف config/broadcast.php. يتضمن الملف مثال ضبط Pusher مما يسمح لك بتخصيص مفتاح، وسر، ومعرف Pusher بسرعة. يسمح مثال الضبط بتخصيص خيارات options أخرى يدعمها Pusher مثل cluster.

'options' => [

   'cluster' => 'eu',
   'encrypted' => true
]

عند استعمال Pusher و Laravel ECHO، يجب تحديد pusher كخيار البث عند بدء نسخة Echo في الملف resources/assets/js/bootstrap.js:

import Echo from "laravel-echo"

window.Pusher = require('pusher-js');

window.Echo = new Echo({

   broadcaster: 'pusher',
   key: 'your-pusher-key'
});

Redis

إذا كنت تستعمل الباث Redis، يجب عليك تثبيت المكتبة Predis:

composer require predis/predis

يبث Redis الأحداث باستخدام الخاصية pub/sub لكن عليك إضافة خادم Websocket ليتلقى رسائل Redis و يبثها لقنوات Websocket.

عندما يبث Redis حدثًا، فسيُنشر على القناة المخصصة للحدث وسيحمل سلسلة محارف مشفرة بطريقة JSON تتضمن اسم الحدث ومعلومات data ومعرف المستخدم الذي صنع التوصيل socket (إن أمكن).

Socket.io

إذا كنت ستضيف Socket.io للباث Redis، ستحتاج لإضافة مكتبة عميل JavaScript للتطبيق. يمكنك تثبيته عبر منظم الخدمات NPM:

npm install --save socket.io-client

ثم عليك بدء Echo بموصل socket.io و host:

import Echo from "laravel-echo"

window.io = require('socket.io-client');

window.Echo = new Echo({

   broadcaster: 'socket.io',
   host: window.location.hostname + ':6001'
});

أخيرا، عليك تشغيل خادم Socket.io متوافق. لا يتضمن Laravel خادم socket.io لكن هنالك خادمٌ يتكفل به المجتمع موجودٌ في github في المستودع tlaverdure/laravel-echo-server.

متطلبات طوابير الانتظار

قبل بث الأحداث, ستحتاج لضبط و تشغيل مستمعي طوابير الانتظار. يتم البث عن طريق مهمات موجودة في قائمات انتظار حتى لا يتأثر وقت اجابة التطبيق.

نظرة عامة على مفهوم البث

يسمح بث الأحداث في Laravel ببث أحداث من جهة الخادم إلى سكربات JavaScript التابعة لتطبيقك من جهة العميل باستخدام مقاربة مبنية على المشغلات في Websockets.

تبث الأحداث في قنوات "channels" قد تكون عامة أو خاصة. يمكن لأي مستخدم للتطبيق أن ينخرط في قناة عامة دون الحاجة لترخيص أو استيثاق. لكن للاستماع على قناة خاصة لا بد من الاستيثاق والترخيص.

استخدام تطبيق مثال

قبل التعمق في كل مكون من بث الأحداث، لنأخذ نظرة عامة على تطبيق تسوق إلكتروني على سبيل المثال. لن ندقق في ضبط Pusher أو Laravel Echo لأن ذلك مذكور في أقسام أخرى من التوثيق.

لنفترض أنّ لدينا في هذا التطبيق صفحة تسمح للمستخدم بالإطلاع على حالة شحن طلب معين. لنفترض أيضًا أن الحدث ShippingStatusUpdated يُطلق كلما تم تحديث حالة طلب شحن يعالجه التطبيق:

event(new ShippingStatusUpdated($update));

الواجهة ShouldBroadcast

عندما يطّلع المستخدم على أحد طلباته، لا نريده أن يُحدّث الصفحة ليرى تحيين الحالة. بل نريد بث تحديثات التطبيق عند إنشائها. لذا يجب إضافة الواجهة ShouldBroadcast للحدث ShippingStatusUpdated. مما سيخبر Laravel أن يبث الحدث عند إطلاقه:

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class ShippingStatusUpdated implements ShouldBroadcast

{

   /**
    * معلومات عن حالة الشحن.
    *
    * @var string
    */
   public $update;
}

تتطلب الواجهة من صنف الحدث تعريف التابع broadcastOn. هذا التابع مسؤول عن إعادة القنوات التي على الحدث البث عليها. يكون التابع فارغًا في كل أصناف الأحداث المُنتجَة ونحتاج فقط لملء التفاصيل. نريد لصاحب الطلب فقط أن يرى حالة الشحن لذا سنبث الحدث على قناة خاصة مرتبطة بالطلب.

/**

* الحصول على معلومات على قناة البث.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()

{

   return new PrivateChannel('order.'.$this->update->order_id);
}

ترخيص القنوات

تذكر انّ المستخدم يجب أن يسجل الدخول ليستمع للقنوات الخاصة. يمكن تعريف قواعد تراخيص القناة في routes/channels.php. في هذا المثال، يجب التأكد من أن المستخدم الذي يريد الاستماع على القناة الخاصة order.1 هو صاحب الطلب:

Broadcast::channel('order.{orderId}', function ($user, $orderId) {

   return $user->id === Order::findOrNew($orderId)->user_id;
});

يقبل التابع channel معاملين: اسم القناة ونداء يُرجع القيمة true أو false للدلالة على إذا كان المستخدم يملك ترخيصًا للاستماع على القناة أم لا. كل نداءات التراخيص تتلقى المستخدم المسجل حاليا كمعامل أول و معامل بديل عن أي معامل إضافي. في هذا المثال، نستخدم البديل {orderId} للإعلام أنّ القسم "ID" من اسم القناة متغير.

الاستماع لبث الحدث

بعد ذلك، كل ما تبقى هو الإستماع للحدث في شيفرة JavaScript للتطبيق. يمكن القيام بهذا باستعمال Laravel Echo. أولًا، نستعمل التابع private للدخول إلى القناة الخاصة. ثم، يمكننا استعمال التابع listen للاستماع للحدث ShippingStatusUpdated. في العادة، كل الخاصيات العامة للحدث تُضمَّن في حدث البث:

Echo.private(`order.${orderId}`)

   .listen('ShippingStatusUpdated', (e) => {
       console.log(e.update);
   });

تعريف أحداث البث

لإعلام Laravel أن حدثا ما يجب بثّه، نفذ الواجهةIlluminate\Contracts\Broadcasting\ShouldBroadcast في صنف الحدث. تُحمَّل هذه الواجهة في كل أصناف الأحداث لذا يمكنك إضافتها بسهولة لأي حدث.

تتطلب الواجهة ShouldBroadcast كتابة تابع وحيد هو broadcastOn. يعيد هذا التابع قناة أو مصفوفة قنوات يبث عليها الحدث. يجب أن تكون القناة نسخة Channel أو PrivateChannel أو PresenceChannel. تمثل نسخة Channel القنوات العامة التي يمكن لأي مستخدم الدخول فيها في حين PrivateChannel و PresenceChannel تمثل قنوات تتطلب ترخيصًا:

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel; use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class ServerCreated implements ShouldBroadcast {

   use SerializesModels;
   public $user;
   /**
    * إنشاء نسخة حدث جديد
    *
    * @return void
    */
   public function __construct(User $user)
   {
       $this->user = $user;
   }
   /**
    * جلب القنوات التي يجب من الحدث البث فيها
    *
    * @return Channel|array
    */
   public function broadcastOn()
   {
       return new PrivateChannel('user.'.$this->user->id);
   }
}

ثم عليك إطلاق حدث كما تفعل عادة. عند إطلاق الحدث، تبث مهمة في قائمة الإنتظار آليًا الحدث على المشغل الذي اخترته.

اسم البث

في العادة، يبث Laravel الأحداث باستخدام أسماء أصناف الأحداث. لكن بإمكانك تخصيص اسم البث عبر تعريف التابع broadcastAs في الحدث:

/**

* اسم الحدث.
*
* @return string
*/
public function broadcastAs() {

   return 'server.created';
}

إذا غيّرت اسم البث باستخدام broadcastAs، يجب عليك التأكد من تسجيل المستمع مسبوقًا بالرمز ".". سيُخبر هذا Echo بإضافة مجال أسماء للحدث:

.listen('.server.created', function (e) {

   ....
});

بيانات البث

عند بث حدث، تتم سلسلة كل خاصياته العامة آليًا كتحميل للحدث، مما يسمح لك بالولوج لكل بياناته العامة من تطبيق JavaScript. لذا لو كان للحدث خاصية واحدة user$ مثلًا تحتوي على نموذج Eloquent، يكون نحميل البث كما يلي:

{

   "user": {
       "id": 1,
       "name": "Patrick Stewart"
       ...
   }
}

لكن إذا أردت تحكما أفضل في تحميل البث، يمكنك إضافة التابع broadcastWith. يعيد هذا التابع مصفوفة البيانات التي تريد إرسالها كتحميل للبث:

/**

* بيانات البث
*
* @return array
*/
public function broadcastWith() {

   return ['id' => $this->user->id];
}

طابور انتظار البث

في العادة، يوضع كل أحداث البث في طابور الانتظار الأولية للصلة الأولية المعرّفة في ملف الضبط queue.php. يمكنك تخصيص طابور انتظار البث عبر تعريف الخاصية broadcastQueue في صنف الحدث. يجب أن تحدد هذه الخاصية اسم طابور الانتظار الذي تود استعماله عند البث:

/**

* اسم قائمة الإنتظار.
*
* @var string
*/
public $broadcastQueue = 'your-queue-name';

إذا أردت بث الأحداث باستعمال طابور الانتظار sync بدل المشغل العادي، يمكنك تنفيذ shouldBroadcastNow بدل ShouldBoradcast:

<?php

use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class ShippingStatusUpdated implements ShouldBroadcastNow

{

  //
}

شروط البث

في بعض الأحيان، قد تريد بث الأحداث فقط إن تحقق شرط معين. يمكنك تحديد هذه الشروط عبر إضافة التابع broadcastWhen لصنف الحدث:

/**

* تحديد إذا كان يجب بث الحدث
*
* @return bool
*/
public function broadcastWhen() {

   return $this->value > 100;
}

الترخيص للقنوات

تتطلب القنوات الخاصة ترخيصًا ليتمكن المستخدم المسجل حاليًا من الإستماع إليها. يتم هذا عبر إطلاق طلب HTTP للتطبيق باسم القناة وجعل التطبيق يقرر هل يسمح للمستخدم بالإستماع أم لا. عند استخدام Laravel Echo، يُصنع طلب HTTP للترخيص بالإنخراط في القنوات الخاصة تلقائيًا. لكن عليك تعريف المسار للإجابة على الطلب.

تعريف مسارات الترخيص

من حسن الحظ، يجعل Laravel تعريف المسارات لإجابة طلبات الترخيص أمرًا سهلًا. في مزود الخدمات BroadcastServiceProvider المضمن في تطبيق Laravel، سترى نداء للتابع Broadcast::routes. سيسجل هذا التابع المسار broadcasting/auth لمعالجة طلبات الترخيص.

Broadcast::routes();

يضع التابع Broadcast::routes آليًا مساراته في في مجموعة الوسيط web لكن بإمكانك تمرير أي صفوفة من خصائص المسارات للتابع إذا أردت تخصيص الخاصيات.

Broadcast::routes($attributes);

تعريف نداءات الترخيص

بعد ذلك، نحتاج لتعريف التحكم المنطقي الذي سيقوم بالترخيص. يتم هذا في الملف routes/channels.php في التطبيق. في هذا الملف، يمكنك استخدام التابع Broadcast::channel لتسجيل نداءات ترخيص القنوات:

Broadcast::channel('order.{orderId}', function ($user, $orderId) {

   return $user->id === Order::findOrNew($orderId)->user_id;
});

يقبل التابع channel معاملين وهما اسم القناة ودالة رد نداء تعيد القيمة true أو false للدلالة على إذا كان المستخدم يملك ترخيصًا للاستماع أم لا. كل نداءات التراخيص تتلقى المستخدم المسجل حاليًا كمعامل أول و معامل بديل عن أي معامل إضافي. في المثال السابق، نستخدم البديل {orderId} للإعلام أنّ القسم "ID" من اسم القناة متغير.

ترخيص نداءات ربط النماذج

مثل مسارات HTTP، تستفيد مسارات القنوات من ربط النماذج المباشر و غير المباشر. مثلًا، بدل تلقي سلسلة محارف أو معرّف رقمي، يمكن أن تطلب نسخة من Order:

use App\Order;

Broadcast::channel('order.{order}', function ($user, Order $order) {

   return $user->id === $order->user_id;
});

تعريف أصناف القنوات

إذا كان التطبيق يستعمل العديد من القنوات، سيصبح الملف routes/channels.php ضخمًا. لذا، بدل استعمال Closure لترخيص القنوات، يمكن استعمال أصناف للقنوات. لإنشاء أصناف القنوات، استعمل الأمر make:channel. سيضع الأمر الأصناف المصنوعة في المجلد App/Broadcasting

php artisan make:channel OrderChannel

ثم سجل الصنف في الملف routes/channels.php

use App\Broadcasting\OrderChannel;

Broadcast::channel('order.{order}', OrderChannel::class);

أخيرًا، يمكنك وضع التحكم المنطقي في الترخيص في الصنف في التابع join. سيحتوي هذا التابع نفس الشيفرة التي كنت ستضعها في عادة في القسم Closure. يمكن طبعًا الاستفادة من ربط النماذج هنا أيضًا.

<?php

namespace App\Broadcasting;

use App\User; use App\Order;

class OrderChannel {

   /**
    * إنشاء نسخة قناة جديدة
    *
    * @return void
    */
   public function __construct()
   {
      //
   }
   /**
    * استيثاق مستخدم القناة
    *
    * @param  \App\User  $user
    * @param  \App\Order  $order
    * @return array|bool
    */
   public function join(User $user, Order $order)
   {
       return $user->id === $order->user_id;
   }
}

ملاحظة: كالعديد من الأصناف في Laravel، تُعالج أصناف القنوات في حاوي الخدمات. لذا يمكنك التلميح إلى نوع الإعتماديات التي تحتاج لها القناة في باني الصنف التي يحتاجها باني الصنف.

بث الأحداث

بعد تعريف الحدث وإضافة الواجهة ShouldBroadcast، تحتاج فقط لإطلاق الحدث باستعمال الدالة event. سيُلاحظ مُطلِق الأحداث أن الحدث تم ترميزه بالواجهة ShouldBroadcast ويضيفه لقائمة انتظار البث:

event(new ShippingStatusUpdated($update));

فقط للآخرين

عند بناء تطبيق يستعمل تقنية البث، يمكنك تعويض الدالة event بالدالة broadcast. مثل event، يُطلق broadcast الحدث من جهة الخادم للمستمع في جهة العميل

broadcast(new ShippingStatusUpdated($update));

لكن الدالة broadcast توفر أيضًا التابع toOthers الذي يسمح باستثناء المستخدم الحالي من لائحة المستقبلين:

broadcast(new ShippingStatusUpdated($update))->toOthers();

لفهم أفضل متى قد تريد استعمال التابع toOthers، لنتخيل تطبيقا للائحة مهام حيث يمكن للمستخدم صناعة مهمة جديدة بتمرير اسم المهمة. لإنشاء مهمة، يبعث التطبيق طلبًا لنقطة النهاية task/ التي تبث صناعة المهمة وتعيد تمثيل JSON للمهمة الجديدة. يتلقى تطبيق javascript الجواب من نقطة النهاية، يمكنه إضافة المهمة الجديدة للائحته كالآتي

axios.post('/task', task)

   .then((response) => {
       this.tasks.push(response.data);
   });

لكن تذكر أننا نبث أيضًا صناعة المهمة، إذا كان تطبيق JavaScript يستمع للحدث ليضيف المهام الجديدة للائحة المهام، سيكون لديك نفس المهمة مرتين: واحد من نقطة النهاية وواحد من البث. يمكن حل هذا المشكل باستخدام التابع toOthers لإعلام الباث بعدم بث الحدث للمستخدم الحالي.

تنبيه: يجب على الحدث استخدام الخاصية Illuminate\Broadcasting\InteractsWithSockets للاستعمال التابع toOthers.

الضبط

عند بدء مثيل Laravel Echo، يُعطى معرّف توصيل (Socket id) للصلة. إذا كنت تستخدم Vue و Axios، يُرفق المعرّف تلقائيًا بكل طلب خارج كعنوان x-socket-ID. ثم عندما تنادي التابع toOthers، يأخذ Laravel المعرّف من العنوان ويأمر الباث بعدن البث لأي صلة تحمل ذلك المعرّف.

إذا كنت لا تستخدم Vue و Axios، ستحتاج لضبط تطبيق JavaScript يدويًا ليُرسل العنوان x-socket-ID. يمكنك استرجاع معرّف التوصيل بالتابع Echo.socketID:

var socketId = Echo.socketId();

تلقي البث

تثبيت Laravel echo

Laravel Echo هي مكتبة Javascript تجعل الانخراط في قناة و والإستماع للأحداث أمرًا سهلًا. يمكنك تثبيت Echo عبر منظم الحزم NPM. في هذا المثال، سنثبت أيضًا pusher-js حيث سنستخدم المشغل pusher للبث:

npm install --save laravel-echo pusher-js

بعد تثبيت Echo، أنت الآن جاهزٌ لإنشاء نسخة Echo في تطبيق JavaScript. نهاية الملف resources/assets/js/bootstrap.js هي مكان جيد للقيام بهذا:

import Echo from "laravel-echo"

window.Echo = new Echo({

   broadcaster: 'pusher',
   key: 'your-pusher-key'
});

عند إنشاء نسخة Echo يستخدم الباث pusher، يمكنك أيضًا تخصيص cluster بالإضافة إلى تحديد إذا ما كانت الصلة تستوجب تشفيرًا:

window.Echo = new Echo({

   broadcaster: 'pusher',
   key: 'your-pusher-key',
   cluster: 'eu',
   encrypted: true
});

الاستماع للأحداث

بعد تثبيت Echo و تشغيله، أنت الآن جاهز للاستماع للأحداث. أولًا، استخدم التابع channel لإعادة نسخة من القناة، ثم استدع التابع listen لحدث معين:

Echo.channel('orders')

   .listen('OrderShipped', (e) => {
       console.log(e.order.name);
   });

إذا أردت الاستماع لأحداث في قناة خاصة، استعمل التابع private بدل channel. يمكنك المواصلة في إضافة نداءات listen للاستماع لعدة أحداث في قناة واحدة

Echo.private('orders')

   .listen(...)
   .listen(...)
   .listen(...);

مغادرة قناة

لمغادرة قناة، ينكنك نداء التابع leave في نسخة Echo:

Echo.leave('orders');

مجالات الأسماء

قد تكون لاحظت في الأمثلة السابقة أننا لم نحدد مجال اسم (namespace) كامل لأصناف الأحداث. هذا لأن Echo يتوقع تلقائيا أن الأحداث موجودة في مجال الأسماء App\Events. لكن يمكنك ضبط جذر مجال الأسماء عند تشغيل Echo بتمرير خيار الضبط namespace

window.Echo = new Echo({

   broadcaster: 'pusher',
   key: 'your-pusher-key',
   namespace: 'App.Other.Namespace'
});

طريقة أخرى هي سبق أصناف الأحداث بنقطة "." عند الانخراط فيها باستعمال Echo. سيسمح لك هذا بذكر اسم كامل للصنف

Echo.channel('orders')

   .listen('.Namespace.Event.Class', (e) => {
      //
   });

قنوات الحضور

تبني قنوات الحضور (presence) على أمان القنوات الخاصة في حين تستغل الخاصية الإضافية بالعلم بمن ينخرط في القناة. مما يسهل من بناء خاصيات قوية وتشاركية مثل تنبيه المستخدم حين يرى مستخدم آخر نفس الصفحة.

ترخيص قنوات الحضور

كل قنوات الحضور قنواتٌ خاصةٌ، لذا، يجب الترخيص للمستخدمين لاستعمالها. لكن عند تعريف نداء ترخيص لقناة حضور، لن تعيد true إذا كان المستخدم مرخصًا له بل يجب أن تعيد مصفوفة ببيانات المستخدم. تكون البيانات الموفّرة من قبل نداء الترخيص متوفِّرة لمستمعي قنوات الحضور في تطبيق JavaScript. إذا لم يكن المستخدم مرخصًا له لدخول القناة، فيجب أن تعيد false أو null:

Broadcast::channel('chat.{roomId}', function ($user, $roomId) {

   if ($user->canJoinRoom($roomId)) {
       return ['id' => $user->id, 'name' => $user->name];
   }
});

الانضمام لقنوات الحضور

للانضمام لقنوات الحضور، يمكنك استعمال التابع join. سيعيد هذا التابع تنفيذًا للتابع PresenceChannel الذي، بالإضافة لتوفير التابع listen، يسمح أيضا بالانخراط في الأحداث here و joining و leaving.

Echo.join(`chat.${roomId}`)

   .here((users) => {
      //
   })
   .joining((user) => {
       console.log(user.name);
   })
   .leaving((user) => {
       console.log(user.name);
   });

يُنفَّذ النداء here مباشرة عند الانضمام الناجح للقناة، ويتلقى مصفوفة من بيانات المستخدم لبقية المستخدمين المنخرطين في القناة. يُنفَّذ التابع joining عندما انضم مستخدم جديد في حين ينفَّذ التابع leaving عندما يغادر مستخدم القناة.

البث لقنوات الحضور

تتلقى قنوات الحضور أحداثًا مثل القنوات العامة أو الخاصة. باستخدام مثال غرف الرسائل، قد نريد بث الحدث NewMessage لقناة حضور الغرفة. للقيم بذلك، سنعيد نسخة PresenceChannel من التابع broadcastOn في الحدث:

/**

*الحصول على قناة البث.
*
* @return Channel|array
*/
public function broadcastOn() {

   return new PresenceChannel('room.'.$this->message->room_id);
}

مثل القنوات العامة والخاصة، يمكن بث أحداث في قنوات الحضور باستخدام الدالة broadcast. كما في بقية الأحداث، يإمكانك استخدام التابع toOthers لاستثناء المستخدم الحالي من تلقي البث:

broadcast(new NewMessage($message));

broadcast(new NewMessage($message))->toOthers();

يمكنك الإستماع لأحداث الإنضمام عبر التابع listen:

Echo.join(`chat.${roomId}`)

   .here(...)
   .joining(...)
   .leaving(...)
   .listen('NewMessage', (e) => {
      //
   });

أحداث العملاء

ملاحظة: عند استعمال Pusher، عليك تفعيل الخيار "Client Events" في القسم "App Settings" من لوحة التحكم لقبول الأحداث من جهة العملاء.

قد تريد في بعض الأحيان بث حدث لبقية المستخدمين دون المرور بتطبيق Laravel. يكون هذا مفيدًا في حالات مثل تنبيهات الكتابة، أين يمكنك أن تُعلم المستخدم أنّ مستخدمًا آخر بصدد الكتابة في شاشة معينة.

لبث أحداث العملاء، يمكن استخدام التابع whisper:

Echo.private('chat')

   .whisper('typing', {
       name: this.user.name
   });

للاستماع لأحداث العملاء، استخدم التابع listenForWhisper:

Echo.private('chat')
    .listenForWhisper('typing', (e) => {
        console.log(e.name);
    });

الإشعارات

عبر إرفاق بث الأحداث بالإشعارات، يتلقى تطبيق JavaScript الإشعارات حين تصل دون الحاجة لتحديث الصفحة. أولا، تأكد من الاطلاع على توثيق الإشعارات.

بعد ضبط التنبيهات لاستخدام قنوات البث، يمكنك الإستماع للأحداث باستعمال التابع notification. تذكر أن اسم القناة يجب أن يوافق اسم صنف الكائن المتلقي لللإشعار:

Echo.private(`App.User.${userId}`)

   .notification((notification) => {
       console.log(notification.type);
   });

في هذا المثال، يتلقى النداء كل التنبيهات المبعوثة إلى App\User عبر القناة broadcast. نداء ترخيص للقناة App.User.{id} يكون مضمنًا في مزود الخدمات BroadcastServiceProvider الذي يأتي مع الإطار Laravel.

مصادر