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

در بخش قبلی به همراه هم تونستیم یک وب‌سوکت‌سرور رو با لاراول راه‌اندازی کنیم. یک کتابخونه نصب کردیم که جایگزین 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 برای ساخت یک چت‌روم استفاده می‌کنیم.حتما اگر سوالی دارید یا ابهام و اشتباهی در مطلبی که نوشتم وجود داره از طریق بخش نظرات با من در ارتباط باشید.استفاده از محتوای مطلبی که نوشتم کاملا آزاد و رایگانه و می‌تونید به دلخواه خودتون با هر نامی اون رو منتشر کنید.