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

在PHP web应用中通过JS向指定用户发送web push通知的方案咨询

定向Web推送通知实现方案

核心实现逻辑

你现有已实现的静态推送是全量给所有订阅用户发送,要实现按device_id定向发送,只需要新增「用户标识-推送订阅」的关联存储逻辑,不需要重构现有推送的核心展示逻辑:

  • 用户授权推送权限时,同步采集当前用户的device_id、登录态中的用户ID,和推送库返回的订阅对象(包含endpoint、授权密钥等Web Push必填参数)一起提交到后端
  • 在你现有的MySQL库中新增推送订阅关联表,存储字段建议为:自增主键、user_id(登录用户ID)、device_id(设备标识)、push_subscription(JSON类型存储完整订阅对象)、is_valid(布尔类型标记订阅是否有效)、create_time
  • 需要发定向告警时,先按照目标device_id或者用户ID从MySQL查询所有有效的订阅记录,遍历调用你现有推送库的发送接口给对应订阅发通知即可

关键代码示例

前端订阅关联逻辑

// 推送授权逻辑,和你现有逻辑兼容
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.ready.then(async reg => {
    // 获取推送订阅对象,和你现有实现一致
    const subscription = await reg.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: '你的VAPID公钥'
    })
    // 采集/生成device_id,存在本地避免重复生成
    let deviceId = localStorage.getItem('custom_device_id')
    if (!deviceId) {
      // 自定义生成唯一device_id的逻辑,可按需求调整
      deviceId = Math.random().toString(36).substring(2) + Date.now().toString(36)
      localStorage.setItem('custom_device_id', deviceId)
    }
    // 提交关联数据到后端存储
    fetch('/api/bind-push-subscription', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        user_id: window.currentLoginUserId, // 从你现有登录逻辑中取当前登录用户ID
        device_id: deviceId,
        subscription: subscription
      })
    })
  })
}

后端定向推送触发逻辑(Node.js示例)

const webpush = require('web-push')
const mysql = require('mysql2/promise')

// 配置VAPID密钥,和你现有推送配置一致
webpush.setVapidDetails(
  'mailto:你的运维联系邮箱',
  '你的VAPID公钥',
  '你的VAPID私钥'
)

/**
 * 定向推送函数
 * @param {Object} filter 筛选条件,支持按device_id或user_id筛选
 * @param {Object} payload 推送内容,包含标题、正文、跳转链接等
 */
async function sendTargetedNotification(filter, payload) {
  const conn = await mysql.createConnection({
    host: '你的MySQL地址',
    user: '数据库用户名',
    password: '数据库密码',
    database: '你的业务库名'
  })

  // 构建查询条件
  let querySql = 'SELECT id, push_subscription FROM push_subscriptions WHERE is_valid = 1'
  const queryParams = []
  if (filter.device_id) {
    querySql += ' AND device_id = ?'
    queryParams.push(filter.device_id)
  }
  if (filter.user_id) {
    querySql += ' AND user_id = ?'
    queryParams.push(filter.user_id)
  }

  const [rows] = await conn.execute(querySql, queryParams)

  // 遍历发送推送
  for (const row of rows) {
    const subscription = JSON.parse(row.push_subscription)
    try {
      await webpush.sendNotification(subscription, JSON.stringify(payload))
    } catch (err) {
      // 发送失败说明订阅已失效,标记为无效避免后续重复发送
      await conn.execute('UPDATE push_subscriptions SET is_valid = 0 WHERE id = ?', [row.id])
    }
  }

  await conn.end()
}

// 调用示例:给指定device_id的用户发送告警
sendTargetedNotification(
  {device_id: '目标用户的device_id'},
  {
    title: '系统告警',
    body: '你负责的业务模块出现异常,请及时处理',
    data: {jumpUrl: '/alarm/detail?id=xxx'}
  }
)

注意事项

  • 若需要支持跨设备推送,同一个用户登录不同设备时会生成不同的device_id,存储多条订阅记录,按user_id筛选时会给该用户所有设备发送通知
  • 推送发送失败时及时清理无效订阅,避免产生不必要的资源消耗
  • 你现有Service Worker中监听push事件展示通知的逻辑无需修改,和现有推送实现完全兼容

内容的提问来源于stack exchange,提问作者Aayush Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:57:05