Thinkphp5 + Swoole实现邮箱异步通知

在 ThinkPHP 中实现邮箱异步通知的常见做法是通过队列系统来处理异步任务,结合 Swoole 来处理异步发送邮件的请求。这样可以避免同步处理邮件发送导致的阻塞,提高响应速度。

以下是基于 ThinkPHP5 框架和 Swoole 的异步邮件通知实现步骤:

一、安装 Swoole

首先,你需要确保 Swoole 已经正确安装,可以通过 Composer 安装:

bash 复制代码
pecl install swoole

二、邮件发送配置

和 Redis 队列的方案一样,我们需要先配置邮件发送,还是使用 PHPMailer 或者其他的邮件库来发送邮件。

在项目的 config.php 中配置邮件相关信息:

php 复制代码
return [
    'email' => [
        'host' => 'smtp.example.com',
        'username' => 'your-email@example.com',
        'password' => 'your-password',
        'port' => 465,
        'from' => 'your-email@example.com',
        'from_name' => 'Your Name',
    ],
];

三、创建邮件服务类

邮件服务类 MailService 负责处理邮件发送的逻辑。这里使用 PHPMailer 作为邮件发送工具。

application/common/service/MailService.php

php 复制代码
<?php

namespace app\common\service;

use PHPMailer\PHPMailer\PHPMailer;
use think\facade\Config;

class MailService
{
    public static function sendMail($to, $subject, $body)
    {
        $mail = new PHPMailer(true);
        try {
            $mail->isSMTP();
            $mail->Host       = Config::get('email.host');
            $mail->SMTPAuth   = true;
            $mail->Username   = Config::get('email.username');
            $mail->Password   = Config::get('email.password');
            $mail->SMTPSecure = 'ssl'; 
            $mail->Port       = Config::get('email.port');

            $mail->setFrom(Config::get('email.from'), Config::get('email.from_name'));
            $mail->addAddress($to);

            $mail->isHTML(true);
            $mail->Subject = $subject;
            $mail->Body    = $body;

            $mail->send();
            return true;
        } catch (\Exception $e) {
            return $mail->ErrorInfo;
        }
    }
}

四、使用 Swoole 实现异步任务

1. 创建 Swoole Server

在项目的 command 目录下创建 SwooleServer.php,用于处理 Swoole 的服务和任务。

php 复制代码
<?php

namespace app\command;

use Swoole\Server;
use app\common\service\MailService;
use think\console\Command;
use think\console\Input;
use think\console\Output;

class SwooleServer extends Command
{
    protected function configure()
    {
        $this->setName('swoole:server')->setDescription('Start Swoole Server');
    }

    protected function execute(Input $input, Output $output)
    {
        $server = new Server("127.0.0.1", 9501);

        // 设置 Swoole 的配置
        $server->set([
            'worker_num' => 4,
            'task_worker_num' => 4,
        ]);

        // 当有客户端连接时触发
        $server->on('receive', function (Server $server, $fd, $reactor_id, $data) {
            // 处理客户端发送的任务数据
            $taskData = json_decode($data, true);

            if ($taskData && isset($taskData['to'], $taskData['subject'], $taskData['body'])) {
                // 投递任务给 Task Worker
                $server->task($taskData);
            }
            $server->send($fd, "Mail task received.");
        });

        // 处理异步任务
        $server->on('task', function (Server $server, $task_id, $from_worker_id, $data) {
            // 使用 MailService 发送邮件
            $result = MailService::sendMail($data['to'], $data['subject'], $data['body']);

            // 返回任务处理结果
            $server->finish($result);
        });

        // 任务处理完成时触发
        $server->on('finish', function (Server $server, $task_id, $data) {
            // 任务完成后的逻辑
        });

        $output->writeln('Swoole Server started.');

        // 启动 Swoole Server
        $server->start();
    }
}
2. 注册 Swoole 命令

application/command.php 中注册 SwooleServer 命令:

php 复制代码
return [
    'app\command\SwooleServer',
];
3. 启动 Swoole Server

使用命令行启动 Swoole Server:

php 复制代码
php think swoole:server

Swoole 服务器启动后,它将监听 127.0.0.1:9501,客户端可以通过这个端口向服务器发送任务请求。

五、在控制器中使用 Swoole 异步发送邮件

现在我们可以在控制器中通过向 Swoole Server 发送请求来处理异步邮件通知。

application/controller/UserController.php

php 复制代码
<?php

namespace app\controller;

use Swoole\Client;
use think\Controller;

class UserController extends Controller
{
    public function register()
    {
        // 用户注册逻辑
        $email = 'user@example.com';
        $subject = '欢迎注册';
        $body = '感谢您注册我们的网站!';

        // 创建一个 Swoole 客户端
        $client = new Client(SWOOLE_SOCK_TCP);

        // 连接到 Swoole Server
        if ($client->connect('127.0.0.1', 9501, 0.5)) {
            // 发送任务数据到 Swoole Server
            $client->send(json_encode([
                'to' => $email,
                'subject' => $subject,
                'body' => $body
            ]));

            // 接收 Swoole Server 的反馈
            $response = $client->recv();
            $client->close();

            return json(['message' => $response]);
        } else {
            return json(['error' => 'Unable to connect to Swoole Server']);
        }
    }
}

六、总结

通过 Swoole 实现的异步任务处理机制,可以将耗时操作如发送邮件等操作放入后台异步执行,提升用户体验和系统性能。Swoole 的 Task 机制非常适合处理这种场景,结合 ThinkPHP 使得开发异步任务更加简单高效。

相关推荐
睆小白34 分钟前
【springboot】实现文件上传和下载
java·spring boot·后端
ChinaRainbowSea40 分钟前
十六,Spring Boot 整合 Druid 以及使用 Druid 监控功能
java·spring boot·后端·spring·web
小ᶻᶻᶻᶻ1 小时前
从零开始搭建 PHP
开发语言·php
.生产的驴1 小时前
Docker 消息队列RabbitMQ 安装延迟消息插件
运维·spring boot·后端·docker·容器·rabbitmq·java-rabbitmq
mit6.8241 小时前
[Linux#49][UDP] 2w字详解 | socketaddr | 常用API | 实操:实现简易Udp传输
linux·网络·c++·笔记·后端
南叔先生2 小时前
Linux 性能优化 copy
网络·数据库·php
.生产的驴2 小时前
SpringBoot 消息队列RabbitMQ死信交换机
java·spring boot·后端·rabbitmq·java-rabbitmq
会敲代码的小张3 小时前
设计模式-观察者模式
java·开发语言·后端·观察者模式·设计模式·代理模式
Flying_Fish_roe7 小时前
Spring Boot-Bean注入问题
spring boot·后端·log4j
.生产的驴8 小时前
SpringBoot 消息队列RabbitMQ 消息可靠性 数据持久化 与 LazyQueue
java·spring boot·后端·eclipse·rabbitmq·maven·java-rabbitmq