
在 Web 应用中实现实时通知,尤其是从后端向前端推送信息,是提升用户体验的关键一环。传统的 HTTP 请求-响应模型无法满足实时性需求。对于 Laravel 和 React 这样的前后端分离架构,常见的实时通信方案包括 WebSockets、Server-Sent Events (SSE) 或第三方实时服务(如 Pusher、Ably)。
原始问题中尝试通过 Laravel 的 Notification 组件结合 React 的 Service Worker 来实现 Web Push 通知。虽然 Service Worker 能够实现原生的 Web Push 通知,但其配置相对复杂,需要处理订阅管理、VAPID 密钥生成、消息加密等一系列步骤。此外,Service Worker 中的 self.addEventListener('push') 事件监听器只有在符合 Web Push 协议的消息被推送时才会触发,并且在开发环境中,self 全局变量在某些 linting 规则下可能会被标记为 no-restricted-globals 错误,这通常是由于 Service Worker 文件被当作普通 JavaScript 文件处理,或者在非 Service Worker 上下文中使用 self 导致的。
为了简化实时通知的实现,并绕过 Web Push 的复杂性以及 Service Worker 相关的潜在问题,使用像 Pusher 这样的实时事件广播服务是一个更高效且易于管理的选择。Pusher 提供了一个基于 WebSocket 的抽象层,允许后端轻松广播事件,前端则通过订阅频道来实时接收这些事件。
Pusher 是一个托管的实时 API,它允许开发者轻松地在 Web 和移动应用中构建实时功能。Laravel 框架原生支持事件广播,并提供了与 Pusher 集成的便捷方式。通过 Pusher,我们可以定义一个事件,在 Laravel 后端触发它,然后 Pusher 会将该事件广播到所有订阅了相应频道的客户端(React 应用)。
首先,我们需要在 Laravel 应用中安装并配置 Pusher。
使用 Composer 安装 Pusher PHP SDK:
composer require pusher/pusher-php-server
确保在 .env 文件中设置了广播驱动为 pusher,并配置 Pusher 的相关凭据。这些凭据可以在 Pusher 仪表盘中获取。
BROADCAST_DRIVER=pusher PUSHER_APP_ID=your-pusher-app-id PUSHER_APP_KEY=your-pusher-app-key PUSHER_APP_SECRET=your-pusher-app-secret PUSHER_APP_CLUSTER=your-pusher-app-cluster # 例如:ap2, mt1, eu
在 config/broadcasting.php 文件中,确认 Pusher 驱动已正确配置:
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true, // 建议开启加密
],
],
// ... 其他广播驱动
],创建一个 Laravel 事件,该事件将实现 ShouldBroadcast 接口。这个接口会告诉 Laravel,该事件应该被广播。
php artisan make:event PushDemoEvent
编辑 app/Events/PushDemoEvent.php 文件:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PushDemoEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public $title;
public $icon;
public $actions;
/**
* 创建一个新的事件实例。
*
* @return void
*/
public function __construct($title, $message, $icon = null, $actions = [])
{
$this->title = $title;
$this->message = $message;
$this->icon = $icon;
$this->actions = $actions;
}
/**
* 获取事件应该广播到的频道。
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
// 这里定义事件广播到的公共频道。
// 如果是私有频道,可以使用 PrivateChannel
return new Channel('notifyChannel');
}
/**
* 获取事件的广播名称。
* 默认情况下,事件的类名被用作广播名称。
* 如果你需要自定义,可以重写此方法。
*
* @return string
*/
public function broadcastAs()
{
return 'notifyEvent'; // 自定义事件名称
}
}
请注意,broadcastOn() 方法返回 new Channel('notifyChannel') 定义了一个公共频道。broadcastAs() 方法定义了事件的名称,前端将通过这个名称监听事件。
在你的控制器(例如 PushController)中,当需要发送通知时,分发这个事件。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Events\PushDemoEvent; // 引入你创建的事件
use Illuminate\Support\Facades\Log;
class PushController extends Controller
{
// ... 其他代码
public function pushNotification()
{
Log::info('Push notification function called');
// 构造通知数据
$title = '新消息!';
$message = '您有一条来自系统的新通知。';
$icon = 'https://example.com/icon.png'; // 可选
$actions = [
['action' => 'view', 'title' => '查看'],
];
// 触发事件,Laravel 会通过 Pusher 将其广播
event(new PushDemoEvent($title, $message, $icon, $actions));
return response()->json(['status' => 'Notification sent via Pusher']);
}
// ... 其他方法
}现在,当 pushNotification 方法被调用时,PushDemoEvent 将会被分发,并通过 Pusher 广播到 notifyChannel 频道,事件名为 notifyEvent。
在 React 应用中,我们需要安装 Pusher JavaScript 客户端,然后订阅 Laravel 广播的频道并监听事件。
在 React 项目中安装 pusher-js:
npm install --save pusher-js # 或者 yarn add pusher-js
在你的 React 组件中,使用 useEffect 钩子来初始化 Pusher 客户端,订阅频道,并绑定事件监听器。
import React, { useEffect, useState } from 'react';
import Pusher from 'pusher-js';
function NotificationComponent() {
const [notifications, setNotifications] = useState([]);
useEffect(() => {
// 确保在组件卸载时清理 Pusher 连接
let pusher = null;
let channel = null;
try {
pusher = new Pusher(process.env.REACT_APP_PUSHER_APP_KEY, {
cluster: process.env.REACT_APP_PUSHER_APP_CLUSTER,
encrypted: true, // 保持与后端配置一致
});
channel = pusher.subscribe("notifyChannel");
channel.bind("notifyEvent", function (data) {
console.log("Received notification:", data);
// 在这里处理接收到的通知数据
// 例如:显示一个弹窗,更新状态,或者使用浏览器 Notification API
setNotifications(prevNotifications => [...prevNotifications, data]);
alert(`新通知: ${data.title} - ${data.message}`);
// 如果想使用浏览器原生通知(与Service Worker不同,这是通过JS触发的)
if (Notification.permission === 'granted') {
new Notification(data.title, {
body: data.message,
icon: data.icon,
actions: data.actions
});
} else if (Notification.permission !== 'denied') {
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
new Notification(data.title, {
body: data.message,
icon: data.icon,
actions: data.actions
});
}
});
}
});
// 绑定成功订阅的事件(可选)
channel.bind('pusher:subscription_succeeded', () => {
console.log('Successfully subscribed to notifyChannel');
});
} catch (error) {
console.error("Pusher initialization failed:", error);
}
// 清理函数:在组件卸载时取消订阅并断开 Pusher 连接
return () => {
if (channel) {
channel.unbind_all(); // 解绑所有事件
pusher.unsubscribe("notifyChannel"); // 取消订阅频道
}
if (pusher) {
pusher.disconnect(); // 断开 Pusher 连接
}
};
}, []); // 空依赖数组表示只在组件挂载和卸载时运行
return (
<div>
<h1>实时通知</h1>
<button onClick={() => console.log('This button now triggers backend to send event')}>
测试通知 (触发后端事件)
</button>
<div>
{notifications.length === 0 ? (
<p>暂无新通知。</p>
) : (
<ul>
{notifications.map((notif, index) => (
<li key={index}>
<strong>{notif.title}:</strong> {notif.message}
</li>
))}
</ul>
)}
</div>
</div>
);
}
export default NotificationComponent;注意事项:
原始问题中提及的 self.addEventListener('push') 和 unexpected use of 'self' no restricted-globals 错误,主要涉及 Web Push API 和 Service Worker 的使用。
使用 Pusher 的优势在于,它完全绕过了 Web Push API 的复杂性。 Pusher 是基于 WebSocket 的实时通信,它不需要 Service Worker 来接收应用内部的实时事件。前端直接通过 WebSocket 连接到 Pusher 服务器,实时接收事件。这使得实现应用内的实时通知变得更加简单和可靠,特别是对于那些不需要在浏览器关闭时也能接收通知的场景。
通过将 Laravel 的事件广播系统与 Pusher 实时服务相结合,我们可以高效且可靠地实现从后端到前端的实时通知功能。这种方法简化了开发流程,避免了 Web Push API 的复杂性以及 Service Worker 相关的潜在问题,为 React 应用提供了流畅的实时用户体验。正确配置 Laravel 事件、Pusher 凭据以及 React 客户端的订阅逻辑是成功的关键。
以上就是Laravel 与 React 实时通知集成:基于 Pusher 的事件广播教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号