محسن میرحسینی
محسن میرحسینی
خواندن ۶ دقیقه·۱ سال پیش

پیاده‌سازی وب‌سوکت‌ها با لاراول - بخش دوم

در بخش قبلی به همراه هم تونستیم یک وب‌سوکت‌سرور رو با لاراول راه‌اندازی کنیم. یک کتابخونه نصب کردیم که جایگزین pusher باشه و وظیفه دریافت و ارسال اطلاعات در کانال‌های ارتباطی بین سرور و کلاینت رو برعهده داشته باشه.

در این بخش سعی می‌کنیم یک کانال ارتباطی در لاراول ایجاد کنیم و اطلاعات رو در این کانال جریان بدیم و همچنین بوسیله جاوااسکریپت در سمت کلاینت به اون متصل بشیم و اطلاعات موجود در کانال رو دریافت کنیم و به صورت یک نوتیفیکیشن نمایششون بدیم. با من همراه باشید تا وارد مرحله بعدی بشیم.

ایجاد یک کانال ارتباطی

حتما قبل از این متوجه شدین که داخل دایرکتوری routes در پروژه لاراول یک فایل با عنوان channels.php وجود داره که تا قبل از این استفاده‌ای ازش نکردیم. در لاراول برای تعریف کانال‌های ارتباطی از این فایل استفاده می‌کنیم. اگر کد زیر رو به فایل channels.php اضافه کنید یک کانال با اسم test-channel ایجاد می‌شه که می‌تونیم جریان اطلاعات رو به اون ارسال یا ازش دریافت کنیم.

Broadcast::channel('test-channel', function () {});

در لاراول ارسال جریان اطلاعات درون یک کانال بوسیله eventها انجام می‌شه. پس برای اینکه بتونیم بوسیله وب‌سوکت کاربر رو از اطلاعات خاصی مطلع کنیم باید یک رخداد پیش بیاد. به ‌عنوان مثال در نظر بگیرید که کاربر در فروشگاه اینترنتی شما مشغول مشاهده محصولاته و شما همون موقع تصمیم می‌گیرید قیمت محصولات رو تغییر بدین. برای اینکه کاربر از بروزرسانی این قیمت‌ها باخبر بشه می‌تونیم یک رخداد تعریف کنیم و در کانال ارتباطی که قبلا کاربر بهش متصل‌شده اطلاعاتی در این خصوص ارسال کنیم. می‌تونیم همه قیمت‌ها رو ارسال کنیم یا در روشی که من بهتر می‌دونم، کلاینت رو باخبر کنیم که باید اطلاعات محصولات رو دوباره از سرور فراخوانی کنه

پس با استفاده از دستور زیر یک رخداد می‌سازیم و سراغ فایل رخداد می‌ریم تا تنظیمات مربوط رو در اون انجام بدیم.

$ php artisan make:event TestWebsocketEvent

اگر به دایرکتوری app/events مراجعه کنید می‌بینید که یک فایل به‌نام TestWebsocketEvent ایجاد شده که در ادامه محتویات اون رو باهم بررسی می‌کنیم.

class TestWebsocketEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; /** * Create a new event instance. */ public function __construct() { } /** * Get the channels the event should broadcast on. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('channel-name'), ]; } }

اولین مساله اینکه این کانال‌های ارتباطی که بین سرور و کلاینت ایجاد می‌شن شامل public channels و private channels هستن و بزرگترین تفاوتشون اینه که در کانال‌های خصوصی می‌تونیم کاربر رو اعتبارسنجی کنیم و متوجه بشیم که کدوم کاربر در حال حاضر به کانال متصل شده. ولی اجازه بدین که در بخش‌های بعدی در این‌خصوص صحبت کنیم و در حال حاضر برای استفاده از یک کانال عمومی فایل رخداد ایجاد‌شده رو به شکل زیر تغییر بدین

class TestWebsocketEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public array $data; /** * Create a new event instance. */ public function __construct() { $this->data = [ 'title' => 'New Notification', 'message' => 'You have new Notification', ]; } /** * Get the channels the event should broadcast on. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ // new PrivateChannel('channel-name'), new Channel('test-channel') ]; } }

اول از همه یک property به این کلاس اضافه کردیم که حاوی اطلاعتیه که قراره توی کانال جریان پیدا‌کنه

public array $data; public function __construct() { $this->data = [ 'title' => 'New Notification', 'message' => 'You have new Notification', ]; }

بعد از اون هم بوسیله متد broadcastOn به لاراول می‌گیم که اطلاعات این رخداد روی کدوم کانال(ها) باید جریان داشته باشه و در حال حاضر از یک کانال عمومی استفاده کردیم که در مرحله قبلی درون فایل broadcast.php اون رو ایجاد کرده بودیم.

public function broadcastOn(): array { return [ // new PrivateChannel('channel-name'), new Channel('test-channel') ]; }

حالا که کانال ارتباطی رو ایجاد کردیم و مشخص شده که چه اطلاعاتی قراره داخلش جریان پیدا کنه باید بریم سمت کلاینت و اونجا به این کانال ارتباطی متصل بشیم.

ارتباط با وب‌سوکت سمت کلاینت

همونطور که قبلا هم گفتم برای استفاده از وب‌سوکت‌ها در سمت کلاینت می‌تونیم از کتابخانه Laravel Echo استفاده کنیم که قابلیت‌های کافی برای این کار رو داره. البته شما می‌تونید از هر کتابخونه دیگه‌ای هم برای این کار استفاده کنید. با استفاده از دستور زیر می‌تونید کتابخونه‌های مورد نیاز رو نصب کنید.

$ npm install --save-dev laravel-echo pusher-js

حالا باید این کتابخونه‌ها رو به بخش فرانت پروژه اضافه کنیم و تنظیمات اولیه رو روشون انجام بدیم.

import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'pusher', key: import.meta.env.VITE_PUSHER_APP_KEY, cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1', wsHost: import.meta.env.VITE_PUSHER_HOST wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https', enabledTransports: ['ws', 'wss'], });

اگر از vite برای bundle کردن فایل‌های پروژه استفاده کرده باشید می‌تونید با استفاده از متغیرهای تعریف شده در فایل env استفاده کنید ولی در هرصورت من مقادیر مورد نیاز رو یک‌بار دیگه توضیح می‌دم.

کلید (key): همون کلید یکتایی که در بخش قبلی در اولین مرحله برای وب‌سوکت سرور ایجاد کردیم و هم در فایل websockets.php و هم فایل broadcasting.php در دایرکتوری config قرارش دادیم.

هاست (wsHost): آدرس دسترسی وب‌سوکت‌سرور

پورت (wsPort): پورت دسترسی به وب‌سوکت‌سرور

در این مرحله باید در کانال وب‌سوکت که در سرور ایجادش گردیم subscribe کنیم یا در اصطلاح عضو بشیم.همچنین باید برای اون رخدادی که قراره توی کانال اطلاعات رو جریان بده گوش بزنگ (listen) باشیم

برای این کار می‌تونید دستورات زیر رو در صفحه اجرا کنید:

Echo.channel('test-channel') .listen('TestWebsocketEvent', (e) => { console.log(e); }) .error(error => { console.log('channel error', error); });

در این مرحله اگر کلاس رخدادی که در لاراول ایجاد کرده بودیم رو اجرای کنید، خصوصیات عمومی کلاس (public properties) به داخل کانال ارتباطی جریان پیدا می‌کنن. البته به‌خاطر داشته باشید که برای این‌کار باید دستور مربوط به اجرای صف (queue)ها رو با مشخصات مورد نظر خودتون به شکل زیر در لاراول اجرا کنید.

$ php artisan queue:work

نمایش نوتیفیکیشن سمت فرانت

برای نمایش نوتیفیکیشن سمت کلاینت می‌تونید بعد از کسب اجازه از کاربر منتظر دریافت اطلاعات از کانال ارتباطی باشید. برای این‌کار می‌تونید از قطعه کد زیر استفاده کنید.

function getNotificationsPermission() { Notification.requestPermission() .then((permission) => { if (permission === &quotgranted&quot) { Echo.channel(`test-channel`) .listen('TestWebsocketEvent', (e) => { const title = e.data.title; const icon = e.data.icon; const body = e.data.message; const notification = new Notification(title, {body, icon}); notification. = function () { window.parent.focus(); notification.close(); } }) .error(error => console.log('channel error', error)); } }); } window.addEventListener('load', () => getNotificationsPermission())

حالا اگر رخدادی که در سمت سرور ساخته بودیم اجرا بشه، اطلاعات اون به‌صورت نوتیفیکیشن سمت کاربر نمایش داده میشه.


در این بخش تونستیم بوسیله وب‌سوکت‌ها یک کانال ارتباطی ایجاد کنیم و با استفاده از یک رخداد، اطلاعات موردنظرمون رو در داخل اون جریان بدیم. همچنین در سمت فرانت با استفاده از کتابخونه Laravel Echo در اون کانال ارتباطی ثبت‌نام کردیم و اطلاعات ارسال شده رو دریافت کردیم. در بخش بعدی با انواع کانال‌های عمومی و خصوصی بیشتر آشنا می‌شیم و از قابلیت‌های کتابخونه Laravel Echo برای ساخت یک چت‌روم استفاده می‌کنیم.

حتما اگر سوالی دارید یا ابهام و اشتباهی در مطلبی که نوشتم وجود داره از طریق بخش نظرات با من در ارتباط باشید.

استفاده از محتوای مطلبی که نوشتم کاملا آزاد و رایگانه و می‌تونید به دلخواه خودتون با هر نامی اون رو منتشر کنید.

لاراول
شاید از این پست‌ها خوشتان بیاید