پیاده سازی نوتیفیکشن ها با لارول - قسمت دوم

با این که مدت خیلی زیادی گذشته ولی بالاخره فرصت این رو پیدا کردم که قسمت دوم این مطلب را آماده کنم. امیدارم قسمت اول رو مطالعه کرده باشین و خوشحال میشم که پیشنهاداتتون در خصوص شیوه نگارش و البته ایراداتی که در مطالبم وجود داره رو برای من بفرستید.این قسمت نوشته هم مثل قبلی ترجمه این مطلب در سایت مدیومه و سعی کردم ضمن ترجمه که البته خیلی دقیق نیست مواردی رو به اون اضافه کنم و تا حدودی بیشتر کاربردیش کنم. مجددا میگم که استفاده از این مطلب حتی بدون ذکر نام من هیچ مانعی نداره و باعث خوشحالی من میشه.در بخش قبلی روش ایجاد یک کلاس نوتیفیکیشن و ارسال اون برای کاربران رو بررسی کردیم. در این بخش سعی میکنم بهتون بگم که چطوری یک شیوه ارسال نوتیفیکیشن یا در واقع یک کانال ارسال نوتیفیکیشن اختصاصی برای خودتون ایجاد کنید. برای مثال ارسال نوتیفیکیشن از طریق فایربیس برای گوشی های دارای سیستم عامل اندروید یا هر مورد دیگه ای که شما میخواین از اون استفاده کنید. در این مثال من ارسال نوتیفیکیشن بوسیله پیامک و استفاده از یکی از سرویس دهندگان پیامک داخلی رو نشونتون میدم که حتم دارم توی خیلی از پروژه ها استفاده میشه.خوب اول از همه باید یه کانال برای ارسال نوتیفیکیشن ایجاد کنیم. حواستون باشه این کانال ها رو با کانال های مربوط به Broadcast در لاراول اشتباه نگیرید. یه دستور ساده آرتیسن وجود داره که کانال ها رو ایجاد میکنه ولی این کانالها به درد ما نمیخورن و باید خودمون کانال ها رو ایجاد کنیم. البته کار بسیار ساده ایه. فقط کافیه در مسیر app/Channels یک کلاس به شکل زیر ایجاد کنید:<?php namespace App\Channels; class MySmsChannel { }به خوبی هم میدونید که اسم کلاس رو هرچی دلتون بخواد میتونید بزارید. برای استفاده از این کانال دو روش وجود داره: روش اول اینه که توی فایل نوتیفیکیشن کلاس رو فراخونی کنید و روش دیگه ثبت اون در یک ServiceProvider هست که به این شکل میتونید انجام بدید:<?php namespace App\Providers;use App\Channels\MySmsChannel; use Illuminate\Support\Facades\Notification; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot() { Notification::extend('sms', function ($app) { return new MySmsChannel(); }); } }البته برای این کار میتونید یه سرویس پرووایدر جدید ایجاد کنید یا همانند مثال از یکی از سرویس پرووایدرهای خود لارول استفاده کنید.خوب حالا برای اینکه کانال ارسال نوتیفیکیشنمون بخوبی کار کنه باید یک متد send بهش اضافه کنیم. این متد به عنوان ورودی یک نمونه از مدلی که قراره براش نوتیفیکیشن ارسال بشه و نمونه ای از کلاس ارسال نوتیفیکیشن رو دریافت می کنه. به قطعه کدی که در ادامه نوشتم توجه کنید:<?php namespace App\Channels; use Illuminate\Notifications\Notification; class MySmsChannel { public function send ($notifiable, Notification $notification) { } }در این متد $notifiable همون مدل (بخونید شخص) نوتیف شونده و $notification هم کلاس نوتیفیکیشنی هست که میخوایم ارسالش کنیم.اینجا باید منطق برناممون رو پیاده سازی کنیم. بدون شک به خود شما بستگی داره که چطور میخواید به شناسه مورد نظر برای ارسال نوتیفیکیشن دست پیدا کنید. مثلا برای ارسال نوتیفیکشن با فایربیس به کلید توکنی احتیاج دارید که توسط اپ موبایل برای شما ارسال شده یا برای ارسال پیامک باید به شماره موبایل کاربر دست پید کنید. بهتره اطلاعات مورد نظر در مدلی که به عنوان ورودی به این متد ارسال کردین وجود داشته باشه. اینطوری وظیفه پیدا کردن شناسه رو به عهده خود مدل میزاریم.خوب در نظر بگیرید برای بدست آوردن شناسه از یک متد استفاده میکنیم که در کلاس مدل تعریف شده و وظیفه اون فقط و فقط برگردوندن اون شناسه (شماره موبایل، آدرس ایمیل، توکن و ...) است. هر اسمی که بخواید میتونید برای اون متد بزارید ولی چه بهتر که از یک الگوی خاص برای این منظور استفاده کنید. به تغییری که در متد send قطعه کد بالا دادم توجه کنید:<?php namespace App\Channels; use Illuminate\Notifications\Notification; use IPPanel\Client; use IPPanel\Errors\Error; use IPPanel\Errors\HttpException; class MySmsChannel { public $apiKey; public $originator; public function __construct() { $this->apiKey = 'xxxxxxxxxxxx'; $this->originator = '+9812345678'; } public function send ($notifiable, Notification $notification) { if (method_exists($notifiable, 'routeNotificationForSms')) { $mobileNumber = $notifiable->routeNotificationForSms($notifiable); } else { //$mobileNumber = $notifiable->mobile_number $mobileNumber = $notifiable->getMobileNumberAttribute(); } $data = method_exists($notification, 'toSms') ? $notification->toSms($notifiable) : $notification->toArray($notifiable); if (empty($data)) { return; } $client = new Client($this->apiKey); try { $client->send($this->originator, $mobileNumber, $data['message']); } catch (Error $e) { Log::channel('notifications')->error(json_encode($e->unwrap())); } catch (HttpException $e) { Log::channel('notifications')->error(json_encode($e->unwrap())); } return true; } }خوب توی این قطعه کد در ابتدا چک میکنیم متد routeNotificationForSms توی کلاس مدلکه قراره نوتیفیکیشن برای اون ارسال بشه وجود داره که بتونیم شماره موبایل کاربر رو ازش دریافت کنیم یا نه؟ اگر این متد وجود نداشته باشه شماره موبایل یا همون شناسه مورد نیازمون رو به طور مستقیم از مدل دریافت می کنیم.اگر به خاطر داشته باشین گفته بودم که برای هر کانال ارسال نوتیفیکیشن در کلاس نوتیفیکیشن باید یک متد مخصوص وجود داشته باشه که وظیفه رسوندن اطلاعات به کانال رو داره. در ادامه چک میکنیم که آیا متد مورد نظرمون در شی ارسال شده به عنوان کلاس نوتیفیکیشن موجود هست یا نه. در صورتی که متد toSms توی کلاس نوتیفیکیشن تعریف نشده باشه از متد toArray استفاده میکنیم که به طور پیشفرض موجوده و از مقادیر خروجی اون برای ارسال پیامک استفاده میکنیم.برای ارسال پیامک من از سامانه ippanel استفاده میکنم که با وجود امکانات بی نظیر و کیفیت فوق العاده هیچ اطلاعاتی از صاحبان اصلیش در اختیار ندارم و پنل خودم رو هم از یکی از نمایندگانشون خریداری کردم. ولی خوب یکی از امکانات خوبشون یک پکیج لاراول جهت ارسال پیامکه که با یک دستور ساده کامپوزر میتونید نصب و ازش استفاده کنید:composer require &quotippanel/php-rest-sdk&quotخوب حالا کلاس مدل که قراره متد routeNotificationForSms و همچنین کلاس نوتیفیکیشن که قراره متد toSms رو پیاده سازی کنن رو کامل میکنیم://User.php <?php namespace App; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use Notifiable; public function routeNotificationForLog ($notifiable) { return 'identifier-from-notification-for-log: ' . $this->id; } }<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; class WelcomeNotification extends Notification { use Queueable; public function __construct () { } public function via ($notifiable) { // The name we used when registering in the provider return [ 'sms' ]; // Alternatively, if not registered in service provider // return [ \App\Channels\SmsChannel::class ]; } public function toSms ($notifiable) { return [ 'message' => sprintf('Dear %s \n Welcome to our website', $notifiable->name), ]; } public function toArray ($notifiable) { return [ 'message' => sprintf('Dear %s \n Welcome to our website', $notifiable->name), ]; } }روش استفاده از این کلاس های نوتیفیکیشن رو هم که حتما میدونید و اگر هم نمیدونید میتونید از قسمت اول این نوشته استفاده کنید:// Approach 1 $user->notify(new WelcomeNotification()); // Approach 2 // Notification::send($user, new WelcomeNotification());امیدوارم مطالبی که نوشتم براتون مفید باشه و بتونید ازش استفاده کنید. خوشحال میشم این مطلب رو به اشتراک بزارید و کمک کنید که افراد بیشتری ازش استفاده کنن.سعی میکنم در آینده اینطور غیبت طولانی نداشته باشم و به زودی مطالب دیگه ای براتون آماده کنم.