PHP项目怎么实现用户生日祝福?

wen java案例 1

本文目录导读:

PHP项目怎么实现用户生日祝福?

  1. 方案概述
  2. 基础实现方案
  3. 多种发送方式
  4. 定时任务实现
  5. 高级功能实现
  6. 最佳实践建议
  7. 部署建议

我来为你详细介绍PHP项目实现用户生日祝福的几种方案。

方案概述

生日祝福功能核心流程:检测生日 → 发送祝福 → 记录状态

基础实现方案

1 数据库设计

-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50),
    email VARCHAR(100),
    birthday DATE,
    last_birthday_wish DATETIME,
    wish_sent_today TINYINT(1) DEFAULT 0
);

2 基础检测脚本

<?php
class BirthdayWish {
    private $db;
    public function __construct($db) {
        $this->db = $db;
    }
    /**
     * 检测并发送生日祝福
     */
    public function checkAndSendWishes() {
        $today = date('m-d');
        $currentYear = date('Y');
        // 查询今天生日的用户
        $sql = "SELECT * FROM users 
                WHERE DATE_FORMAT(birthday, '%m-%d') = ? 
                AND (last_birthday_wish IS NULL 
                     OR DATE(last_birthday_wish) != CURDATE())";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$today]);
        $users = $stmt->fetchAll();
        foreach ($users as $user) {
            $this->sendBirthdayWish($user);
        }
    }
    /**
     * 发送祝福
     */
    private function sendBirthdayWish($user) {
        // 计算年龄
        $age = date('Y') - date('Y', strtotime($user['birthday']));
        // 准备祝福内容
        $message = "亲爱的{$user['username']},祝你{$age}岁生日快乐!";
        // 发送方式:邮件
        $this->sendEmail($user['email'], '生日祝福', $message);
        // 更新发送记录
        $this->updateWishRecord($user['id']);
    }
    /**
     * 更新祝福记录
     */
    private function updateWishRecord($userId) {
        $sql = "UPDATE users 
                SET last_birthday_wish = NOW(), 
                    wish_sent_today = 1 
                WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$userId]);
    }
}

多种发送方式

1 邮件发送

<?php
use PHPMailer\PHPMailer\PHPMailer;
class EmailSender {
    public function sendBirthdayEmail($to, $name, $age) {
        $mail = new PHPMailer(true);
        try {
            $mail->isSMTP();
            $mail->Host = 'smtp.gmail.com';
            $mail->SMTPAuth = true;
            $mail->Username = 'your@email.com';
            $mail->Password = 'your-password';
            $mail->SMTPSecure = 'tls';
            $mail->Port = 587;
            $mail->setFrom('noreply@yourdomain.com', '生日祝福');
            $mail->addAddress($to, $name);
            $mail->Subject = '🎂 生日快乐!';
            // HTML模板
            $mail->isHTML(true);
            $mail->Body = "
                <div style='max-width:600px;margin:0 auto;padding:20px;text-align:center;'>
                    <h1>🎉 生日快乐!</h1>
                    <p>亲爱的 {$name}:</p>
                    <p>今天是你的{$age}岁生日,</p>
                    <p>祝你生日快乐,万事如意!</p>
                    <div style='font-size:48px;'>🎂🎁🎊</div>
                </div>
            ";
            $mail->send();
            return true;
        } catch (Exception $e) {
            error_log("邮件发送失败: " . $mail->ErrorInfo);
            return false;
        }
    }
}

2 短信发送(使用阿里云)

<?php
use AlibabaCloud\Client\AlibabaCloud;
class SMSSender {
    public function sendBirthdaySMS($phone, $name) {
        AlibabaCloud::accessKeyClient('your-access-key', 'your-access-secret')
            ->regionId('cn-hangzhou')
            ->asDefaultClient();
        try {
            $result = AlibabaCloud::rpc()
                ->product('Dysmsapi')
                ->version('2017-05-25')
                ->action('SendSms')
                ->method('POST')
                ->host('dysmsapi.aliyuncs.com')
                ->options([
                    'query' => [
                        'PhoneNumbers' => $phone,
                        'SignName' => '你的签名',
                        'TemplateCode' => 'SMS_123456789',
                        'TemplateParam' => json_encode([
                            'name' => $name
                        ])
                    ]
                ])
                ->request();
            return $result->toArray();
        } catch (Exception $e) {
            error_log("短信发送失败: " . $e->getMessage());
            return false;
        }
    }
}

定时任务实现

1 Linux Crontab

# 每天早上8点执行
0 8 * * * /usr/bin/php /path/to/birthday_wish.php
# 每小时执行一次
0 * * * * /usr/bin/php /path/to/birthday_wish.php

2 完整的定时任务脚本

#!/usr/bin/php
<?php
// birthday_wish.php - 定时任务入口
require_once 'config/database.php';
require_once 'vendor/autoload.php';
class BirthdayWishCron {
    private $birthdayWish;
    private $emailSender;
    public function __construct() {
        $db = new PDO("mysql:host=localhost;dbname=test", "root", "");
        $this->birthdayWish = new BirthdayWish($db);
        $this->emailSender = new EmailSender();
    }
    public function execute() {
        echo "[" . date('Y-m-d H:i:s') . "] 开始检测生日用户...\n";
        $today = date('m-d');
        $db = $this->getDb();
        // 查询今天生日的用户
        $stmt = $db->prepare("
            SELECT * FROM users 
            WHERE DATE_FORMAT(birthday, '%m-%d') = ?
            AND (last_birthday_wish IS NULL 
                 OR DATE(last_birthday_wish) != CURDATE())
        ");
        $stmt->execute([$today]);
        $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
        echo "发现 " . count($users) . " 位生日用户\n";
        foreach ($users as $user) {
            $this->processUser($user);
        }
        echo "[" . date('Y-m-d H:i:s') . "] 处理完成\n";
    }
    private function processUser($user) {
        $age = date('Y') - date('Y', strtotime($user['birthday']));
        echo "发送祝福给: {$user['username']} ({$age}岁)\n";
        // 发送邮件
        $emailResult = $this->emailSender->sendBirthdayEmail(
            $user['email'],
            $user['username'],
            $age
        );
        if ($emailResult) {
            echo "✓ 邮件发送成功\n";
            $this->updateWishRecord($user['id']);
        } else {
            echo "✗ 邮件发送失败\n";
        }
    }
}
// 执行
$cron = new BirthdayWishCron();
$cron->execute();

高级功能实现

1 个性化祝福模板

<?php
class BirthdayTemplate {
    private $templates = [
        'friend' => "亲爱的{name},{age}岁生日快乐!愿你永远年轻,永远热泪盈眶!",
        'colleague' => "尊敬的{name},祝您{age}岁生日快乐,工作顺利,家庭幸福!",
        'vip' => "尊贵的VIP用户{name},感谢您的一路相伴,祝您{age}岁生日快乐!我们还为您准备了专属优惠券:{coupon}"
    ];
    public function getPersonalizedWish($user) {
        $template = $this->templates[$user['type']] ?? $this->templates['friend'];
        $replacements = [
            '{name}' => $user['username'],
            '{age}' => $this->calculateAge($user['birthday']),
            '{coupon}' => $this->generateCoupon($user['id'])
        ];
        return str_replace(array_keys($replacements), $replacements, $template);
    }
    private function calculateAge($birthday) {
        $birth = new DateTime($birthday);
        $now = new DateTime();
        return $birth->diff($now)->y;
    }
    private function generateCoupon($userId) {
        return "BIRTHDAY" . date('Ymd') . $userId;
    }
}

2 批量发送优化

<?php
class BatchBirthdaySender {
    private $messageQueue = [];
    private $maxBatchSize = 50;
    public function addToQueue($user, $message) {
        $this->messageQueue[] = [
            'user' => $user,
            'message' => $message
        ];
        if (count($this->messageQueue) >= $this->maxBatchSize) {
            $this->flushQueue();
        }
    }
    public function flushQueue() {
        if (empty($this->messageQueue)) {
            return;
        }
        // 批量插入发送记录
        $this->batchInsertRecords($this->messageQueue);
        // 批量发送邮件(使用队列系统)
        foreach ($this->messageQueue as $item) {
            // 推送到消息队列
            Queue::push('sendEmail', $item);
        }
        $this->messageQueue = [];
    }
    private function batchInsertRecords($records) {
        $sql = "INSERT INTO birthday_wish_log (user_id, sent_at, status) VALUES ";
        $values = [];
        $params = [];
        foreach ($records as $index => $record) {
            $values[] = "(?, NOW(), 'pending')";
            $params[] = $record['user']['id'];
        }
        $sql .= implode(', ', $values);
        // 执行批量插入
    }
}

最佳实践建议

1 时区处理

date_default_timezone_set('Asia/Shanghai');

2 防重复机制

// 使用Redis防止重复发送
$redisKey = "birthday:send:{$userId}:" . date('Ymd');
if ($redis->exists($redisKey)) {
    return; // 今天已发送
}
// 发送逻辑...
$redis->setex($redisKey, 86400, 1);

3 异常处理

try {
    // 发送逻辑
} catch (Exception $e) {
    // 记录日志
    error_log("生日祝福发送失败: " . $e->getMessage());
    // 重试机制
    $retryCount = 0;
    while ($retryCount < 3) {
        if ($this->retrySend($user)) {
            break;
        }
        $retryCount++;
        sleep(5);
    }
}

部署建议

  1. 使用消息队列:Redis、RabbitMQ处理大量发送请求
  2. 日志记录:记录每次发送的状态便于排查
  3. 监控告警:设置发送失败告警
  4. 限流控制:避免短时间内大量发送被封
  5. 用户隐私:注意用户隐私保护,提供退订功能

这个方案可以根据项目规模灵活调整,从小型项目到大型系统都可以适用。

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