怎样在PHP项目中实现缺货提醒?

wen java案例 7

本文目录导读:

怎样在PHP项目中实现缺货提醒?

  1. 核心思路
  2. 方案一:基于MySQL定时任务 + 邮件/短信(适合中小型项目)
  3. 方案二:事件驱动 + Redis Pub/Sub(适合中等规模)
  4. 方案三:用户端的“到货通知”(用户订阅模式)
  5. 方案四:推送通知(WebSocket / SSE)(面向C端用户实时提醒)
  6. 进阶方案:实时库存 + 消息队列 + 多渠道
  7. 选型建议

在PHP项目中实现缺货提醒,通常需要结合库存监控通知机制以及用户偏好设置,以下是几种常见的实现方案,从简单到复杂:

核心思路

  1. 监控库存:每次订单生成或库存变动时,检查当前库存量。
  2. 判断阈值:如果库存低于预设的“安全库存”或“缺货线”,则触发提醒。
  3. 发送通知:通过邮件、短信、站内信或WebSocket推送通知相关方(管理员、用户)。

基于MySQL定时任务 + 邮件/短信(适合中小型项目)

这是最传统且无需额外服务的方法,适合库存变动不频繁的场景。

数据库设计

products表添加min_stock(最低库存预警线)字段。 在orders表(或库存日志表)记录每次扣减。

创建PHP脚本

<?php
// check_low_stock.php
require_once 'config.php'; // 数据库连接等配置
$threshold = 10; // 假设低于10件为缺货
// 查询库存低于阈值的商品
$sql = "SELECT id, name, stock, min_stock
        FROM products
        WHERE stock < ? AND stock > 0"; // 排除无库存的
$stmt = $pdo->prepare($sql);
$stmt->execute([$threshold]);
$lowStockItems = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($lowStockItems)) {
    // 发送邮件给管理员
    $to = "admin@example.com";
    $subject = "库存预警提醒";
    $message = "以下商品库存不足:\n\n";
    foreach ($lowStockItems as $item) {
        $message .= "商品ID: {$item['id']} - {$item['name']} (库存: {$item['stock']})\n";
    }
    mail($to, $subject, $message);
    // 可选:记录到提醒日志表
}

设置Cron任务(Linux)或计划任务(Windows)

# 每5分钟执行一次检查
*/5 * * * * /usr/bin/php /path/to/check_low_stock.php

缺点

  • 实时性差(取决于Cron执行间隔)。
  • 高并发下可能漏发(因库存变化快)。
  • 无法主动推送给用户。

事件驱动 + Redis Pub/Sub(适合中等规模)

利用Redis的发布/订阅或队列,在库存变更时立即触发提醒。

库存更新时发布事件

// 当扣减库存时(例如在订单创建成功后的代码中)
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 检查更新后的库存
$newStock = $productModel->getStock($productId);
$threshold = 10;
if ($newStock < $threshold && $newStock > 0) {
    $event = json_encode([
        'type' => 'low_stock',
        'product_id' => $productId,
        'current_stock' => $newStock,
        'timestamp' => time()
    ]);
    // 发布到频道
    $redis->publish('stock_alert', $event);
}

后台Worker订阅并处理

// worker.php (独立进程运行)
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->subscribe(['stock_alert'], function ($redis, $channel, $message) {
    $data = json_decode($message, true);
    // 发送邮件/短信/钉钉/企业微信通知
    sendAlertEmail($data['product_id'], $data['current_stock']);
    // 记录日志
    logAlert($data);
});

通过php worker.php在后台常驻运行,或使用Supervisor管理。

优点:实时性强,无需轮询数据库。


用户端的“到货通知”(用户订阅模式)

如果想让用户主动订阅缺货商品,并在到货时提醒他们:

用户订阅表

CREATE TABLE `stock_subscriptions` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `user_id` int(11) NOT NULL,
    `product_id` int(11) NOT NULL,
    `email` varchar(255) NOT NULL,
    `status` tinyint(4) DEFAULT '0', -- 0:等待中, 1:已通知
    `created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    UNIQUE KEY `user_product` (`user_id`, `product_id`)
);

补货时触发

// 当补货操作完成(入库、退货、供应商送货)
public function restockProduct($productId, $quantity) {
    // 更新库存...
    $product->stock += $quantity;
    $product->save();
    // 检查是否有用户订阅了该商品
    $subscriptions = StockSubscription::where('product_id', $productId)
                                       ->where('status', 0)
                                       ->get();
    // 如果库存从0变为>0,且用户订阅存在
    if ($product->stock > 0 && $subscriptions->count() > 0) {
        foreach ($subscriptions as $sub) {
            // 发送邮件给订阅用户
            $this->sendBackInStockEmail($sub->email, $product);
            // 标记为已通知
            $sub->status = 1;
            $sub->save();
        }
    }
}

优化:使用队列(如RabbitMQ、Beanstalkd)将邮件发送任务异步化,避免阻塞补货流程。


推送通知(WebSocket / SSE)(面向C端用户实时提醒)

如果需要在前端实时显示“库存紧张”或缺货,推荐使用Server-Sent Events (SSE)或WebSocket

使用SSE示例(PHP Server-Sent Events)

// sse.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
$lastId = 0;
while (true) {
    // 每次循环检查当前登录用户关注的商品库存
    $userId = $_SESSION['user_id']; // 或从JWT获取
    $lowStockProducts = $db->query("
        SELECT p.id, p.name, p.stock 
        FROM products p 
        JOIN user_wishlist uw ON p.id = uw.product_id
        WHERE uw.user_id = ? AND p.stock < p.min_stock
    ", [$userId])->fetchAll();
    if (!empty($lowStockProducts)) {
        echo "id: " . ++$lastId . "\n";
        echo "event: low_stock\n";
        echo "data: " . json_encode($lowStockProducts) . "\n\n";
        ob_flush();
        flush();
    }
    sleep(10); // 每10秒检查一次
}

前端通过EventSource接收:(但注意SSE对缺货场景的轮询效率较低,更适合推送新消息)


进阶方案:实时库存 + 消息队列 + 多渠道

组件 技术选型 用途
库存扣减 Redis + Lua脚本(原子操作) 保证高并发下库存准确
事件触发 RabbitMQ/Redis List 异步处理库存变更事件
通知分发 PHP Worker (Supervisor) 轮询队列,区分通知类型
通知渠道 Mailgun/SendGrid (邮件), Twilio (短信), 钉钉/企微机器人 根据重要性选择渠道
用户偏好 数据库表 用户选择“邮件/短信/App推送”

示例:RabbitMQ消费者

// consumer.php
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('stock_alert_queue', false, true, false, false);
$callback = function ($msg) {
    $data = json_decode($msg->body, true);
    if ($data['type'] === 'low_stock') {
        // 根据用户设置的通知方式发送
        if ($data['notification_type'] === 'email') {
            sendEmail($data['user_email'], $data['message']);
        } elseif ($data['notification_type'] === 'sms') {
            sendSMS($data['phone'], $data['message']);
        }
    }
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_consume('stock_alert_queue', '', false, false, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

选型建议

场景 推荐方案 理由
小型电商站,管理员关心缺货 Cron + 邮件 简单,无需额外组件
用户可订阅到货通知 订阅表 + 队列 体验好,用户主动参与
实时库存页面显示“紧张” WebSocket/SSE 前端实时感知
高并发、大流量(秒杀后) 方案二/进阶:Redis + RabbitMQ 解耦,可靠,不拖垮数据库
需要多渠道通知(邮件、短信、App) 进阶方案:消息队列 + 渠道适配器 灵活扩展

关键提醒

  • 对于到货通知,务必在补货成功、库存从0变为>0时触发,而非每次库存变化都触发,避免骚扰用户。
  • 邮件通知最好加入退订链接,符合GDPR/反垃圾邮件法规。
  • 高并发下,建议使用Redis + Lua扣减库存,避免数据库行锁和性能问题。

抱歉,评论功能暂时关闭!