Laravel 与 React 实时通知集成:基于 Pusher 的事件广播教程

心靈之曲
发布: 2025-10-10 13:37:25
原创
809人浏览过

laravel 与 react 实时通知集成:基于 pusher 的事件广播教程

本文旨在指导开发者如何在 Laravel 后端与 React 前端之间实现实时通知功能。我们将重点介绍如何利用 Pusher 这一实时事件广播服务,从 Laravel 后端发送通知,并在 React 应用中实时接收并处理这些通知,从而有效解决传统 Web Push API 配置复杂及 self 全局变量报错等常见问题,构建流畅的用户体验。

理解实时通知的挑战与解决方案

在 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 事件广播

Pusher 是一个托管的实时 API,它允许开发者轻松地在 Web 和移动应用中构建实时功能。Laravel 框架原生支持事件广播,并提供了与 Pusher 集成的便捷方式。通过 Pusher,我们可以定义一个事件,在 Laravel 后端触发它,然后 Pusher 会将该事件广播到所有订阅了相应频道的客户端(React 应用)。

Laravel 后端配置

首先,我们需要在 Laravel 应用中安装并配置 Pusher。

1. 安装 Pusher 依赖

使用 Composer 安装 Pusher PHP SDK:

composer require pusher/pusher-php-server
登录后复制

2. 配置广播驱动

确保在 .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, // 建议开启加密
        ],
    ],
    // ... 其他广播驱动
],
登录后复制

3. 创建并广播事件

创建一个 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() 方法定义了事件的名称,前端将通过这个名称监听事件。

集简云
集简云

软件集成平台,快速建立企业自动化与智能化

集简云 22
查看详情 集简云

4. 在控制器中触发事件

在你的控制器(例如 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 前端集成

在 React 应用中,我们需要安装 Pusher JavaScript 客户端,然后订阅 Laravel 广播的频道并监听事件。

1. 安装 Pusher JS 客户端

在 React 项目中安装 pusher-js

npm install --save pusher-js
# 或者
yarn add pusher-js
登录后复制

2. 初始化 Pusher 实例并订阅频道

在你的 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;
登录后复制

注意事项:

  • process.env.REACT_APP_PUSHER_APP_KEY 和 process.env.REACT_APP_PUSHER_APP_CLUSTER 是从环境变量中获取 Pusher 凭据的示例。在实际项目中,你需要在 .env 文件中定义这些变量(例如 REACT_APP_PUSHER_APP_KEY=your-key),React 应用会自动加载它们。
  • pusher.subscribe("notifyChannel") 订阅的频道名称必须与 Laravel 后端 broadcastOn() 方法中返回的频道名称一致。
  • channel.bind("notifyEvent", ...) 监听的事件名称必须与 Laravel 后端 broadcastAs() 方法中定义的事件名称一致(如果 broadcastAs() 被重写,否则默认是事件类名)。
  • useEffect 的清理函数非常重要,它确保在组件卸载时正确地断开 Pusher 连接并取消订阅,防止内存泄漏和不必要的网络请求。

关于 Service Worker 与 self 错误

原始问题中提及的 self.addEventListener('push') 和 unexpected use of 'self' no restricted-globals 错误,主要涉及 Web Push API 和 Service Worker 的使用。

  1. self 错误: self 是 Service Worker 的全局作用域对象,类似于浏览器窗口中的 window。no-restricted-globals 错误通常是 ESLint 或其他 linter 工具的警告,它可能认为你在非 Service Worker 上下文(如普通前端 JavaScript 文件)中使用了 self,或者在 Service Worker 文件中,由于某些配置,它被视为不安全的全局变量。要解决这个 linter 错误,通常需要在 ESLint 配置中为 Service Worker 文件指定正确的环境(如 worker 或 serviceworker),或者禁用相应的规则。
  2. Service Worker push 事件未触发: 即使 self 错误被解决,self.addEventListener('push') 未触发通常意味着后端没有按照 Web Push 协议正确地发送推送消息。Laravel 的 Notification 组件虽然可以用于发送 Web Push 通知(通过 NotificationChannels\WebPush 等包),但它需要一套完整的配置,包括用户订阅、VAPID 密钥管理等。如果这些配置不完整或消息格式不正确,Service Worker 就不会收到 push 事件。

使用 Pusher 的优势在于,它完全绕过了 Web Push API 的复杂性。 Pusher 是基于 WebSocket 的实时通信,它不需要 Service Worker 来接收应用内部的实时事件。前端直接通过 WebSocket 连接到 Pusher 服务器,实时接收事件。这使得实现应用内的实时通知变得更加简单和可靠,特别是对于那些不需要在浏览器关闭时也能接收通知的场景。

注意事项与最佳实践

  1. Pusher Key 安全性: 永远不要将 Pusher 的 APP_SECRET 暴露在前端代码中。只有 APP_KEY 和 APP_CLUSTER 可以在前端使用。
  2. 错误处理: 在 Pusher 客户端初始化和事件绑定时,添加适当的错误处理机制,例如 try-catch 块。
  3. 用户体验: 收到通知后,不仅仅是 alert(),更应该考虑如何以非侵入式的方式向用户展示通知,例如使用 Toast 提示、更新通知中心图标、或显示在页面顶部的横幅。
  4. 授权频道(Private Channels): 如果你的通知需要针对特定用户发送,或者包含敏感信息,你应该使用 Pusher 的授权频道(Private Channels)。这需要在 Laravel 后端实现一个授权路由,Pusher 客户端在订阅私有频道前会向该路由发送请求进行身份验证。
  5. 离线处理: Pusher 主要处理实时在线通知。如果用户离线,他们将不会收到实时事件。对于离线通知,仍然可能需要结合传统的 Web Push API 或其他机制(如消息队列和邮件/短信通知)。
  6. 替代方案: 除了 Pusher,你也可以考虑使用其他实时服务(如 Ably)或自建 WebSocket 服务器(如使用 Laravel Echo Server 结合 Redis 或 Socket.io)。Pusher 的优势在于其托管服务和与 Laravel 的良好集成。

总结

通过将 Laravel 的事件广播系统与 Pusher 实时服务相结合,我们可以高效且可靠地实现从后端到前端的实时通知功能。这种方法简化了开发流程,避免了 Web Push API 的复杂性以及 Service Worker 相关的潜在问题,为 React 应用提供了流畅的实时用户体验。正确配置 Laravel 事件、Pusher 凭据以及 React 客户端的订阅逻辑是成功的关键。

以上就是Laravel 与 React 实时通知集成:基于 Pusher 的事件广播教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号