You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel实时通知系统问题:无法无刷新接收消息

Laravel实时通知无法刷新接收的问题修复

一、排查现有轮询方案的问题

1. 控制器查询缓存问题

你当前的控制器里用$user->unreadNotifications->where(...)是对已加载的Eloquent集合进行过滤,这个集合在用户登录后就被缓存了,不会每次请求都从数据库拉取最新数据。所以即使有新通知,轮询也拿不到。

修复方法:改用查询构造器,每次都查询数据库:

public function getNotifications(Request $request)
{
    $user = auth()->user();
    // 使用查询构造器,每次请求都从数据库获取最新未读通知
    $demands = $user->unreadNotifications()->where('type', '!=', 'App\Notifications\NewMessageNotification')->get();
    $messages = $user->unreadNotifications()->where('type', 'App\Notifications\NewMessageNotification')->get();

    $response = [
        'demands' => $demands->map(function($notification) {
            $typeDemande = $notification->data['type_demande'] ?? 'Non spécifié';
            $status = $notification->data['status'] ?? null;
            $userName = $notification->data['user_name'] ?? 'Utilisateur non spécifié';

            $message = isset($status)
                ? "Votre demande de type $typeDemande a été $status."
                : "Nouvelle demande de type $typeDemande par l'utilisateur $userName";

            return [
                'id' => $notification->id,
                'type' => 'demand',
                'message' => $message
            ];
        }),
        'messages' => $messages->map(function($notification) {
            $sender = $notification->data['sender'] ?? 'Expéditeur inconnu';
            return [
                'id' => $notification->id,
                'type' => 'message',
                'message' => "Nouveau message de $sender"
            ];
        }),
        'countDemands' => $demands->count(),
        'countMessages' => $messages->count()
    ];

    return response()->json($response);
}

2. 路由名称不匹配

你提到路由是newnotification,但前端JS里用的是{{ route('newnotifications') }}(复数),这会导致请求404,轮询失败。打开浏览器控制台的Network标签,检查每次fetch请求的状态码,如果是404,修正路由名称一致:

  • 要么把路由名称改成newnotifications
  • 要么把JS里的route('newnotifications')改成route('newnotification')

3. 前端调试验证

打开浏览器控制台,查看:

  • 每次updateNotifications执行时,请求是否发送成功
  • 响应的JSON数据里有没有新的通知
  • 如果请求成功但数据为空,检查数据库里的通知是否标记为未读,以及用户关联是否正确

二、升级为真正的实时推送(替代轮询)

轮询会有延迟且浪费服务器资源,推荐用Laravel的官方实时方案:

1. 配置Laravel Echo + Pusher

  • 安装依赖:
composer require pusher/pusher-php-server
npm install laravel-echo pusher-js
  • 配置.env:
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=你的PusherID
PUSHER_APP_KEY=你的PusherKey
PUSHER_APP_SECRET=你的PusherSecret
PUSHER_APP_CLUSTER=你的集群(比如mt1)
  • 修改config/broadcasting.php里的pusher配置,确保options里的cluster和.env一致

2. 修改通知类

让你的通知类实现ShouldBroadcast接口,比如NewMessageNotification:

use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class NewMessageNotification extends Notification implements ShouldBroadcast
{
    public function via($notifiable)
    {
        return ['database', 'broadcast']; // 同时保存到数据库和推送
    }

    public function toBroadcast($notifiable)
    {
        return new BroadcastMessage([
            'sender' => $this->sender->name,
            // 其他需要的字段
        ]);
    }
}

3. 前端监听推送

在Blade视图的JS里替换轮询逻辑,改为监听推送:

<script src="{{ mix('js/app.js') }}"></script>
<script>
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: '{{ env('PUSHER_APP_KEY') }}',
    cluster: '{{ env('PUSHER_APP_CLUSTER') }}',
    forceTLS: true
});

// 监听当前用户的通知频道
window.Echo.private(`App.Models.User.{{ auth()->id() }}`)
    .notification((notification) => {
        // 收到新通知时,直接更新UI或者调用updateNotifications刷新
        updateNotifications();
        // 或者直接添加新通知到列表顶部
        addNotificationToList(notification);
    });

// 保留原来的updateNotifications函数用于初始化和手动刷新
function updateNotifications() {
    // 原有的fetch逻辑...
}

// 页面加载时初始化一次
updateNotifications();
</script>

这样有新通知时会立即推送到前端,无需轮询。


内容的提问来源于stack exchange,提问作者web developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:47:32