iguazoft/yii2-sse-notification 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

iguazoft/yii2-sse-notification

Composer 安装命令:

composer require iguazoft/yii2-sse-notification

包简介

Yii2 Server-Sent Events & Web Push Notification Extension

README 文档

README

Real-time notifications for Yii2 applications using Server-Sent Events (SSE) and Web Push (VAPID).

Latest Stable Version Total Downloads License

Features

  • Server-Sent Events (SSE) - Real-time notifications for online users
  • Web Push Notifications (VAPID) - Browser notifications for offline users
  • Automatic Routing - Intelligently routes notifications via SSE or Web Push
  • Multiple Notification Types - Private, authenticated broadcast, and public
  • Flexible Storage - Redis and ActiveRecord drivers included
  • Service Worker - Pre-configured for Web Push
  • Connection Management - Automatic online/offline detection
  • Modern UI - Toast notifications with customizable styling

Requirements

  • PHP >= 8.1
  • Yii2 >= 2.0.14
  • One of:
    • Redis (recommended for production)
    • MongoDB
    • MySQL/PostgreSQL (via ActiveRecord)

Installation

Install via Composer:

composer require iguazoft/yii2-sse-notification

Quick Start

1. Configure the Module

Add the SSE module to your config/web.php:

'modules' => [
    'sse' => [
        'class' => 'iguazoft\sse\Module',
        'vapid' => [
            'subject' => 'mailto:admin@yourdomain.com',
            'publicKey' => 'YOUR_VAPID_PUBLIC_KEY',
            'privateKey' => 'YOUR_VAPID_PRIVATE_KEY',
        ],
    ],
],

2. Generate VAPID Keys

Generate your VAPID keys for Web Push:

# Using web-push CLI
npx web-push generate-vapid-keys

# Or using PHP
vendor/bin/web-push generate-vapid-keys

3. Configure Storage Driver

Choose your notification storage driver in config/web.php:

Option A: Redis (Recommended)

'components' => [
    'redis' => [
        'class' => 'yii\redis\Connection',
        'hostname' => 'localhost',
        'port' => 6379,
        'database' => 0,
    ],
],
'container' => [
    'definitions' => [
        'iguazoft\sse\interfaces\NotificationSourceInterface' => [
            'class' => 'iguazoft\sse\drivers\RedisDriver',
        ],
    ],
],

Option B: ActiveRecord (MySQL/PostgreSQL)

'container' => [
    'definitions' => [
        'iguazoft\sse\interfaces\NotificationSourceInterface' => [
            'class' => 'iguazoft\sse\drivers\ActiveRecordDriver',
            'notificationClass' => 'app\models\Notification',
        ],
    ],
],

4. Run Database Migration

Create the required tables:

php yii migrate --migrationPath=@vendor/iguazoft/yii2-sse/src/migrations

This creates:

  • notification - Stores notifications (if using ActiveRecord)
  • push_subscription - Stores Web Push subscriptions
  • user_connection - Tracks online/offline status

5. Copy Service Worker

Copy the Service Worker to your web root:

cp vendor/iguazoft/yii2-sse/src/assets/sw.js web/sw.js

6. Add to Layout

Include the SSE assets in your layout (views/layouts/main.php):

<?php
use iguazoft\sse\assets\SseAsset;
use yii\helpers\Url;

SseAsset::register($this);

$sseUrl = Url::to(['/sse/stream/index']);
$pushConfig = json_encode([
    'publicKey' => Yii::$app->getModule('sse')->vapid['publicKey'],
    'subscriptionUrl' => Url::to(['/sse/push/subscribe']),
    'serviceWorkerUrl' => '/sw.js',
]);

$this->registerJs("
    const sseClient = new NotificationClient('$sseUrl');
    const pushClient = new PushClient($pushConfig);
    
    // Bind Subscribe Button
    const btnSub = document.getElementById('btn-subscribe');
    if (btnSub) {
        btnSub.addEventListener('click', () => {
            pushClient.subscribe().then(() => {
                alert('Successfully subscribed to notifications!');
            }).catch(err => {
                console.error('Subscription failed', err);
            });
        });
    }
");
?>

<!-- Notification container -->
<div id="notification-container" style="position: fixed; top: 70px; right: 20px; z-index: 9999; width: 350px;"></div>

7. Add Subscribe Button (Optional)

Add a button to allow users to subscribe to Web Push:

<button id="btn-subscribe" class="btn btn-primary">
    🔔 Subscribe to Notifications
</button>

Usage

Sending Notifications

Method 1: Using NotificationDispatcher

use iguazoft\sse\components\NotificationDispatcher;
use Yii;

$dispatcher = Yii::createObject(NotificationDispatcher::class);

// Send private notification
$dispatcher->send([
    'type' => 'private',
    'user_id' => 123,
    'message' => [
        'title' => 'New Message',
        'body' => 'You have a new message from John',
        'icon' => '/images/notification-icon.png',
        'url' => '/messages/view/456',
    ],
]);

Method 2: Using HTTP Endpoint

curl -X POST http://yourapp.com/index.php?r=sse/notification/create \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "type=private" \
  -d "user_id=123" \
  -d "message[title]=New Message" \
  -d "message[body]=You have a new message"

Method 3: Direct Driver Access

use iguazoft\sse\interfaces\NotificationSourceInterface;
use Yii;

$driver = Yii::createObject(NotificationSourceInterface::class);

$driver->createNotification([
    'type' => 'private',
    'user_id' => 123,
    'message' => [
        'title' => 'Direct Notification',
        'body' => 'Sent directly via driver',
    ],
]);

Notification Types

Private Notification - Sent to a specific user:

[
    'type' => 'private',
    'user_id' => 123,
    'message' => [...],
]

Authenticated Broadcast - Sent to all authenticated users:

[
    'type' => 'auth_broadcast',
    'message' => [...],
]

Public Broadcast - Sent to all connected users (including guests):

[
    'type' => 'public',
    'message' => [...],
]

Message Format

'message' => [
    'title' => 'Notification Title',      // Required
    'body' => 'Message content',          // Required
    'icon' => '/path/to/icon.png',        // Optional
    'badge' => '/path/to/badge.png',      // Optional
    'url' => '/target/page',              // Optional - where to redirect on click
    'data' => [                           // Optional - custom data
        'id' => 123,
        'type' => 'message',
    ],
]

How It Works

Intelligent Routing

The extension automatically routes notifications based on user status:

┌─────────────────────────┐
│  Notification Created   │
└───────────┬─────────────┘
            │
            ▼
    ┌───────────────┐
    │ Is User       │
    │ Online?       │
    └───┬───────┬───┘
        │       │
    YES │       │ NO
        │       │
        ▼       ▼
   ┌─────┐   ┌──────────┐
   │ SSE │   │ Web Push │
   └─────┘   └──────────┘
      │            │
      ▼            ▼
   Toast     OS Notification

SSE Flow (Online Users)

  1. User opens your app
  2. SSE connection established to /sse/stream/index
  3. Notification created → stored in Redis/DB
  4. SSE stream picks up notification
  5. JavaScript displays toast notification

Latency: < 2 seconds

Web Push Flow (Offline Users)

  1. User subscribes via browser
  2. Subscription saved to database
  3. User goes offline/closes browser
  4. Notification created → user detected as offline
  5. Push sent via VAPID to FCM/Mozilla servers
  6. Browser receives push event
  7. Service Worker displays OS notification

Latency: 2-10 seconds

Configuration Reference

Module Configuration

'modules' => [
    'sse' => [
        'class' => 'iguazoft\sse\Module',
        
        // VAPID keys for Web Push (required)
        'vapid' => [
            'subject' => 'mailto:admin@example.com',
            'publicKey' => 'YOUR_PUBLIC_KEY',
            'privateKey' => 'YOUR_PRIVATE_KEY',
        ],
    ],
],

Driver Configuration

Redis Driver (Recommended)

'container' => [
    'definitions' => [
        'iguazoft\sse\interfaces\NotificationSourceInterface' => [
            'class' => 'iguazoft\sse\drivers\RedisDriver',
            'keyPrefix' => 'sse:',  // Optional, default: 'sse:'
        ],
    ],
],

ActiveRecord Driver

'container' => [
    'definitions' => [
        'iguazoft\sse\interfaces\NotificationSourceInterface' => [
            'class' => 'iguazoft\sse\drivers\ActiveRecordDriver',
            'notificationClass' => 'app\models\Notification',  // Your AR model
        ],
    ],
],

Advanced Usage

Custom Notification Model

Create your own ActiveRecord model:

namespace app\models;

use yii\db\ActiveRecord;

class Notification extends ActiveRecord
{
    public static function tableName()
    {
        return 'notification';
    }
    
    public function rules()
    {
        return [
            [['type', 'message'], 'required'],
            [['user_id'], 'integer'],
            [['message'], 'safe'],
        ];
    }
}

Customizing Toast Notifications

Override the default toast styling in your CSS:

.notification-toast {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-radius: 12px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}

.notification-toast .title {
    font-weight: 700;
    font-size: 16px;
}

.notification-toast .body {
    opacity: 0.9;
}

Manually Managing Connections

use iguazoft\sse\components\ConnectionManager;
use Yii;

$cm = Yii::createObject(ConnectionManager::class);

// Mark user as online
$cm->connect(123);

// Check if user is online
if ($cm->isOnline(123)) {
    echo "User is connected";
}

// Mark user as offline
$cm->disconnect(123);

Direct PushService Usage

use iguazoft\sse\components\PushService;
use Yii;

$pushService = Yii::createObject(PushService::class);

// Send to specific user
$result = $pushService->sendToUser(123, [
    'title' => 'Direct Push',
    'body' => 'Sent directly via PushService',
    'data' => ['url' => '/dashboard'],
]);

print_r($result);
// Output: Array ( [0] => Sent to {subscription_id}: OK )

Troubleshooting

Notifications Not Appearing

SSE (Online Users)

  1. Check browser console for connection errors
  2. Verify SSE route is accessible: /index.php?r=sse/stream/index
  3. Check Redis/DB for stored notifications
  4. Ensure NotificationClient is initialized
  5. Verify CORS headers if using different domains

Web Push (Offline Users)

  1. Check browser permissions: Settings → Notifications → Allow
  2. Verify VAPID keys are correct
  3. Ensure Service Worker is registered: chrome://serviceworker-internals
  4. Check subscription exists in database
  5. On macOS: Chrome must be open (minimized is OK)

VAPID Errors

InvalidConfigException: VAPID keys are not configured

Solution: Ensure the sse module is loaded and VAPID keys are set in config/web.php.

Service Worker Not Found

GET /sw.js 404 (Not Found)

Solution: Copy sw.js to your web root:

cp vendor/iguazoft/yii2-sse/src/assets/sw.js web/sw.js

Subscription Fails for Guest Users

{status: "error", message: "You must be logged in"}

Solution: Ensure users are authenticated before subscribing to push notifications.

Architecture

Components

Component Purpose
NotificationDispatcher Routes notifications to SSE or Web Push
PushService Handles Web Push via VAPID
ConnectionManager Tracks user online/offline status
StreamController Serves SSE stream
NotificationController Provides notification creation API
PushController Handles push subscriptions

Drivers

Driver Storage Production Ready
RedisDriver Redis Lists ✅ Yes (Recommended)
ActiveRecordDriver MySQL/PostgreSQL ✅ Yes
MongoDriver MongoDB ⚠️ Experimental

Assets

File Purpose
sse.js SSE client (EventSource)
push.js Web Push client
sw.js Service Worker for push events

Security Considerations

  1. CSRF Protection: Enabled by default on all endpoints
  2. Authentication: Web Push subscriptions require authenticated users
  3. VAPID Keys: Keep private key secret, never expose in client-side code
  4. HTTPS Required: Web Push only works over HTTPS (except localhost)

Performance

Recommended Limits

  • Concurrent SSE Connections: Up to 10,000 per server
  • Notification Rate: Up to 1,000/second (Redis driver)
  • TTL for Stored Notifications: 24 hours (configurable)
  • Web Push Queue: Up to 100 pending per user

Optimization Tips

  1. Use Redis driver for production
  2. Implement message queue for bulk notifications
  3. Add CDN for static assets (sw.js, icons)
  4. Use Redis Pub/Sub for multi-server deployments
  5. Implement notification batching for high-volume scenarios

License

This extension is available under a dual license model:

Option 1: AGPL-3.0 (Free for Open Source)

Use this extension for free if your project is open source and licensed under AGPL-3.0 or a compatible license. You must:

  • ✅ Release your application source code under AGPL-3.0
  • ✅ Disclose all source code (including for SaaS applications)
  • ✅ License derivative works under AGPL-3.0

Option 2: Commercial License (For Proprietary Use)

If your application is closed-source, commercial, or proprietary, you must purchase a Commercial License. This includes:

  • ✅ No requirement to open source your code
  • ✅ Use in proprietary applications
  • ✅ Priority support and updates
  • ✅ Legal indemnification

📧 Purchase a Commercial License: licensing@iguazoft.com

See the LICENSE file for complete details.

Support

Credits

Developed by Iguazoft

Powered by:

iguazoft/yii2-sse-notification 适用场景与选型建议

iguazoft/yii2-sse-notification 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「real-time」 「yii2」 「sse」 「Server-Sent Events」 「Web Push」 「vapid」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 iguazoft/yii2-sse-notification 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 iguazoft/yii2-sse-notification 我们能提供哪些服务?
定制开发 / 二次开发

基于 iguazoft/yii2-sse-notification 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 21
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: AGPL-3.0-or-later
  • 更新时间: 2026-02-06