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

如何使用Laravel向桌面端特定用户发送推送通知?

桌面端特定用户推送通知实现方案

你当前遇到页面重载就触发通知的核心原因:Push.create 通知触发逻辑直接写在页面全局加载流中,没有做「当前用户是否为通知接收人」「是否存在未读新通知」的前置判断,只要页面刷新代码就执行,自然会出现误触发。
具体实现按以下步骤改造即可:

一、后端逻辑改造

1. 优化现有通知存储逻辑

你当前的store方法存在重复查询数据库的问题,循环内重复查询用户信息完全可以复用已有查询结果,优化后代码如下:

public function store(Request $request)
{
    // 一次性查询目标用户,避免循环内重复查库
    $targetUsers = User::where('user_type',1)->where('status',1)->get(['id','email']);
    foreach($targetUsers as $user){
        $userNotification = new UserNotification();
        $userNotification->user_id = $user->id;
        $userNotification->notification_id = $notification->id;
        $userNotification->is_read = 0; // 补充已读状态字段,默认未读
        $userNotification->save();

        $details = ['email' => $user->email];
        $emailJob = (new UserNotificationMailJob($details))->delay(Carbon::now()->addMinutes(1));
        dispatch($emailJob);
    }
    Session::flash('message','Notification is SuccessFully Sent');
    return redirect()->back();
}

2. 新增当前用户未读通知查询接口

新增接口专门返回当前登录用户本人的未读新通知,加时间过滤避免历史未读通知每次刷新都重复弹出,示例代码:

// 通知控制器内新增方法,配置对应路由即可
public function getMyUnreadNotifications()
{
    $currentUser = auth()->user();
    // 只查询当前用户最近30分钟内的未读通知,可根据业务调整时间范围
    $unreadList = UserNotification::with('notification')
        ->where('user_id', $currentUser->id)
        ->where('is_read', 0)
        ->where('created_at', '>', now()->subMinutes(30))
        ->get();

    return response()->json([
        'code' => 0,
        'data' => $unreadList
    ]);
}

3. 新增通知标记已读接口

通知被用户点击/展示后标记为已读,避免重复推送,示例逻辑:

public function markNotificationRead($id)
{
    UserNotification::where('id', $id)
        ->where('user_id', auth()->id())
        ->update(['is_read' => 1]);
    return response()->json(['code' => 0]);
}

二、前端逻辑改造

1. 移除全局直接触发的通知代码

把原来直接写在页面加载逻辑里的裸Push.create代码全部删掉,从根源解决刷新就弹的问题。

2. 增加前置判断再触发通知

页面加载后先校验通知权限,再拉取当前用户本人的未读通知,只有存在有效未读通知时才触发弹窗,示例代码:

document.addEventListener('DOMContentLoaded', function() {
    // 先检查浏览器通知权限,无权限时先申请权限
    if (!Push.Permission.has()) {
        Push.Permission.request();
        return;
    }

    // 拉取当前登录用户的未读通知,接口地址替换为你自己的路由
    fetch('/notification/my-unread', {
        method: 'GET',
        credentials: 'same-origin' // 自动携带登录态cookie
    })
    .then(res => res.json())
    .then(res => {
        if (res.code !== 0 || !res.data.length) return;

        // 遍历未读通知逐个弹出
        res.data.forEach(notifyItem => {
            Push.create(notifyItem.notification.title || 'Work From Here', {
                body: notifyItem.notification.content || "You have new Notification!",
                timeout: 5000,
                icon: iconPath,
                onClick: function() {
                    // 点击通知跳转到对应业务页面
                    window.location.href = notifyItem.notification.target_url || '/';
                    this.close();
                    // 标记通知已读,避免下次刷新重复弹
                    fetch(`/notification/read/${notifyItem.id}`, {
                        method: 'POST',
                        credentials: 'same-origin'
                    });
                }
            });
        })
    })
})

三、实时推送优化(可选)

如果需要实现「后端发通知后用户无需刷新页面立刻收到」的效果,可以用WebSocket私有频道方案:后端发通知时向对应用户的私有频道推送事件,前端登录后监听自己的私有频道,收到事件后再触发Push.create即可,这种方案精准度更高,完全不会出现给非目标用户弹通知的问题。

功能相关截图

内容的提问来源于stack exchange,提问作者zubair syslab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:30:10