وب پوش نوتیفیکیشن در لاراول با WebPush Channel
خلاصهٔ کاملتر
وب پوش نوتیفیکیشن یه قابلیت جذابه که بهت اجازه میده حتی وقتی کاربر تب مرورگرش رو بسته، بهش پیام بفرستی — بدون اینکه اپ نیتیو داشته باشی. پکیج WebPush Channel از پروژهی Laravel Notification Channels این امکان رو مستقیم به سیستم نوتیفیکیشن لاراول اضافه میکنه. به هیچ سرویس واسطی نیاز نیست؛ ارتباط مستقیماً با Push API مرورگر از طریق کلیدهای VAPID برقرار میشه.
بعد از نصب پکیج، باید تریت HasPushSubscriptions رو به مدل User اضافه کنی. این تریت متدهای لازم برای ذخیره و مدیریت سابسکریپشنهای کاربران رو در اختیارت میذاره. بعدش با دستور php artisan webpush:vapid یه جفت کلید VAPID تولید میکنی که به .env اضافه میشن. کلید عمومی با مرورگر به اشتراک گذاشته میشه و کلید خصوصی پیامهای خروجی رو امضا میکنه. مهم اینه که این کلیدها رو عوض نکنی، چون هر سابسکریپشن موجود به همون جفت کلیدی که با اون ساخته شده گره خورده.
در سمت کلاینت، دو چیز نیاز داری: یه سرویس ورکر که پوشها رو در پسزمینه دریافت و نمایش بده، و یه فراخوانی PushManager.subscribe() برای گرفتن آبجکت سابسکریپشن از مرورگر. توجه داشته باش که Push API فقط روی HTTPS کار میکنه (localhost استثناست).
سرویس ورکر در فایل public/sw.js نوشته میشه و رویداد push رو گوش میده:
self.addEventListener('push', function (event) {
let data = {};
try { data = event.data?.json() ?? {}; }
catch (e) { data = { title: 'Notification', body: event.data?.text() ?? '' }; }
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body, icon: data.icon, data: data.data, actions: data.actions,
})
);
});برای سابسکرایب کردن کاربر، باید این فرآیند رو به یه کلیک دکمه وصل کنی، چون مرورگرها اجازه نمایش پرامپت درخواست دسترسی رو بدون تعامل مستقیم کاربر نمیدن. بعد از اینکه کاربر اجازه داد، سابسکریپشن گرفته میشه و به سرور ارسال میشه:
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(
document.querySelector('meta[name="vapid-public-key"]').content
),
});
const { endpoint, keys: { p256dh, auth } } = subscription.toJSON();در سمت سرور، اطلاعات سابسکریپشن رو با متد updatePushSubscription روی کاربر ذخیره میکنی. مدیریت سابسکریپشنهای منقضی هم خودکاره؛ وقتی یه تحویل با خطای endpoint منقضی برگرده، پکیج اون سابسکریپشن رو از دیتابیس پاک میکنه.
برای ارسال نوتیفیکیشن، یه کلاس نوتیفیکیشن معمولی لاراول مینویسی و WebPushChannel رو به متد via() اضافه میکنی. متد toWebPush() پیام رو میسازه:
public function toWebPush($notifiable, $notification): WebPushMessage
{
return (new WebPushMessage)
->title('GOAL! ' . $this->team)
->icon('/icons/football.png')
->body("{$this->scorer} scores in the {$this->minute}' ⚽")
->action('View match', 'view_match')
->data(['url' => '/matches/live'])
->options(['TTL' => 60]);
}WebPushMessage تمام امکانات Push API رو پوشش میده: عنوان، متن، آیکون، badge، image، tag، vibrate، requireInteraction و غیره. TTL کوتاه مثلاً برای اعلان گل فوتبال منطقیه چون نوتیفیکیشنی که یه ساعت بعد برسه دیگه فایدهای نداره.
در نهایت مقاله به DeclarativeWebPushMessage هم اشاره میکنه که یه رویکرد جدیدتره. در این روش منطق نمایش نوتیف به خود مرورگر منتقل میشه نه سرویس ورکر، که برای حریم خصوصی و مصرف باتری موبایل مزایایی داره. پشتیبانی مرورگرها ازش هنوز محدوده ولی APIش خیلی شبیه WebPushMessage معمولیه.
نکات کلیدی:
- بدون سرویس شخص ثالث، مستقیم با Push API مرورگر کار میکنه
- کلیدهای VAPID رو هرگز عوض نکن؛ همه سابسکریپشنها به اونها وابستهن
- Push API فقط روی HTTPS کار میکنه (localhost استثناست)
- سافاری نیاز به VAPID_SUBJECT داره وگرنه خطای BadJwtToken میده
- سابسکریپشنهای منقضیشده بهصورت خودکار از دیتابیس پاک میشن
- DeclarativeWebPushMessage گزینهای جدیدتر با مزایای حریم خصوصی و باتریه ولی پشتیبانی مرورگرها هنوز کامل نیست
- ارسال نوتیف دقیقاً مثل سایر نوتیفیکیشنهای لاراوله: notify() روی کاربر




