Laravel推送用WebPush吗

wen PHP项目 8

本文目录导读:

Laravel推送用WebPush吗

  1. 为什么选择 WebPush?
  2. 在 Laravel 中实现 WebPush
  3. 高级配置
  4. 注意事项
  5. 是否推荐使用 WebPush?

在 Laravel 中实现浏览器推送通知,强烈推荐使用 WebPush 协议,Laravel 生态中最常用的包是 laravel-notification-channels/webpush,它基于 W3C 的 Push API 和 Service Workers 实现标准化的浏览器推送。

为什么选择 WebPush?

核心优势

  1. 标准协议:基于 W3C Push API + Service Workers
  2. 跨平台兼容:支持 Chrome、Firefox、Edge、Safari 16.4+
  3. 无需 App Key:使用 VAPID(Voluntary Application Server Identification)认证
  4. 后台推送:即使浏览器关闭也能收到通知(依赖系统通知服务)

与替代方案对比

方案 适用场景 缺点
WebPush 标准浏览器推送 需要 Service Worker
Pusher Channels 实时WebSocket通信 非推送通知,需页面打开
Firebase Cloud Messaging (FCM) 原生App + Web Google服务依赖,国内受限
SSE (Server-Sent Events) 单向实时推送 非浏览器推送API

在 Laravel 中实现 WebPush

安装包

composer require laravel-notification-channels/webpush

生成 VAPID 密钥

php artisan webpush:vapid

这会配置 .env 文件:

VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:your-email@example.com

创建数据迁移

php artisan make:migration create_push_subscriptions_table
Schema::create('push_subscriptions', function (Blueprint $table) {
    $table->id();
    $table->morphs('subscribable');
    $table->string('endpoint', 500)->unique();
    $table->string('public_key', 100)->nullable();
    $table->string('auth_token', 100)->nullable();
    $table->string('content_encoding', 20)->nullable();
    $table->timestamps();
});

前端实现(JavaScript + Service Worker)

注册 Service Worker

// resources/js/app.js
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js')
        .then(reg => console.log('SW registered', reg))
        .catch(err => console.error('SW registration failed', err));
}
// 订阅推送
async function subscribeUser() {
    const registration = await navigator.serviceWorker.ready;
    const subscription = await registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('{{ $vapidPublicKey }}')
    });
    // 保存到服务器
    await fetch('/api/subscribe', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(subscription)
    });
}

Service Worker (public/sw.js)

self.addEventListener('push', event => {
    const data = event.data.json();
    const options = {
        body: data.body,
        icon: '/icon.png',
        badge: '/badge.png',
        data: {
            url: data.url
        }
    };
    event.waitUntil(
        self.registration.showNotification(data.title, options)
    );
});
self.addEventListener('notificationclick', event => {
    event.notification.close();
    if (event.notification.data.url) {
        clients.openWindow(event.notification.data.url);
    }
});

创建通知类

php artisan make:notification PushNotification
use NotificationChannels\WebPush\WebPushChannel;
use NotificationChannels\WebPush\WebPushMessage;
class PushNotification extends Notification
{
    public function via($notifiable)
    {
        return [WebPushChannel::class];
    }
    public function toWebPush($notifiable, $notification)
    {
        return (new WebPushMessage)
            ->title('新消息通知')
            ->body('您有一条新消息')
            ->action('查看详情', 'view')
            ->data(['url' => route('messages.show', 1)]);
    }
}

添加 Notifiable Trait 到 User 模型

use NotificationChannels\WebPush\HasPushSubscriptions;
class User extends Authenticatable
{
    use HasPushSubscriptions;
}

发送通知

$user->notify(new PushNotification());
// 或批量发送
Notification::send($users, new PushNotification());

高级配置

自定义 Service Worker 路径

// config/webpush.php
'service_worker' => '/custom-sw.js',

设置通知超时

'guzzle' => [
    'timeout' => 5,
    'connect_timeout' => 5,
],

处理过期订阅

// 在订阅更新方法中
use NotificationChannels\WebPush\WebPushChannel;
public function updateSubscription(Request $request)
{
    $user = $request->user();
    $user->deletePushSubscriptions();
    $user->updatePushSubscription($request->input('endpoint'), [
        'public_key' => $request->input('keys.p256dh'),
        'auth_token' => $request->input('keys.auth'),
    ]);
    return response()->json(['success' => true]);
}

注意事项

HTTPS 要求

浏览器推送必须通过 HTTPS 或 localhost 使用

用户权限

  • 用户必须主动授权通知权限
  • 不支持静默推送

浏览器兼容性

  • Chrome 50+ ✅
  • Firefox 44+ ✅
  • Edge 79+ ✅
  • Safari 16.4+ ✅ (需要 macOS Ventura 13.3+)

国内特殊考虑

  • 如果使用自建 Push Service,确保网络可访问
  • 某些浏览器(如部分国产浏览器)可能不完全支持

是否推荐使用 WebPush?

强烈推荐,尤其是在以下场景:

  • ✅ 需要离线推送通知(浏览器关闭也能收到)
  • ✅ 标准 Web 应用,不需要原生 App 支持
  • ✅ 跨平台兼容性要求高
  • ✅ 预算有限,不希望依赖第三方推送服务

可能不适合的场景:

  • ❌ 需要即时双向通信(用 WebSocket 更合适)
  • ❌ 需要原生 App 推送(考虑 FCM/APNs)
  • ❌ 用户群体主要使用旧版浏览器(< 2018 年版本)

对于标准的浏览器推送通知需求,WebPush 是 Laravel 生态中的最佳实践选择,它提供了完整的订阅管理、通知格式化和可靠送达机制,并且与 Laravel 的 Notification 系统完美集成。

抱歉,评论功能暂时关闭!