ThinkPHP6 集成 MQTT 协议
一、前置准备
- MQTT 服务端:需先部署 MQTT 服务器(如 EMQ X、Mosquitto),记录服务端地址、端口(默认 1883)、用户名 / 密码(如有)
二、安装 MQTT 客户端依赖
推荐使用 PHP 生态中成熟的 php-mqtt/client 包(支持 MQTT 3.1/3.1.1/5.0,无需编译扩展),通过 Composer 安装:
composer require php-mqtt/client
三、配置 MQTT 连接信息
在 ThinkPHP6 的
config 目录下新建 mqtt.php 配置文件,统一管理连接参数:<?php // config/mqtt.php return [ // MQTT 服务端地址 'host' => env('MQTT_HOST', '127.0.0.1'), // 端口(TCP 默认 1883,SSL 默认 8883) 'port' => env('MQTT_PORT', 1883), // 客户端 ID(唯一,建议加随机数避免冲突) 'client_id' => env('MQTT_CLIENT_ID', 'tp6_mqtt_' . uniqid()), // 用户名(无则留空) 'username' => env('MQTT_USERNAME', ''), // 密码(无则留空) 'password' => env('MQTT_PASSWORD', ''), // 保持连接时间(秒) 'keep_alive' => 60, // 是否启用 SSL/TLS 'use_ssl' => false, // QoS 等级(0/1/2,按需选择) 'qos' => 0, ];
可在 .env 文件中配置实际参数,避免硬编码:
[MQTT] MQTT_HOST=127.0.0.1 MQTT_PORT=1883 MQTT_USERNAME=zyw MQTT_PASSWORD=zyw123456
四、封装 MQTT 工具类
在
app/common/lib 目录下创建 MqttClient.php,封装连接、发布、订阅等核心方法:
<?php // app/common/lib/MqttClient.php namespace app\common\lib; use PhpMqtt\Client\MqttClient as Client; use PhpMqtt\Client\ConnectionSettings; use think\facade\Config; use think\facade\Log; class MqttClient { // MQTT 客户端实例 private static $client = null; // 初始化连接 private static function connect() { if (self::$client !== null) { return self::$client; } // 读取配置 $config = Config::get('mqtt'); //halt($config); $host = $config['host']; $port = $config['port']; $clientId = $config['client_id']; // 连接配置 $connectionSettings = (new ConnectionSettings) ->setUsername($config['username']) ->setPassword($config['password']) ->setKeepAliveInterval($config['keep_alive']) ->setUseTls($config['use_ssl']); // 创建客户端实例 self::$client = new Client($host, $port, $clientId); try { // 连接服务器 self::$client->connect($connectionSettings, true); Log::info('MQTT 连接成功'); } catch (\Exception $e) { Log::error('MQTT 连接失败:' . $e->getMessage()); self::$client = null; throw new \Exception('MQTT 连接失败:' . $e->getMessage()); } return self::$client; } /** * 发布消息 * @param string $topic 主题 * @param string $message 消息内容 * @param int $qos QoS 等级(0/1/2) * @param bool $retain 是否保留消息 * @return bool */ public static function publish(string $topic, string $message, int $qos = null, bool $retain = false) { $client = self::connect(); if ($client === null) { return false; } $qos = $qos ?? Config::get('mqtt.qos'); try { // 发布消息 $client->publish($topic, $message, $qos, $retain); // 确保消息发送完成 $client->loop(true, 100); Log::info("MQTT 发布消息成功,主题:{$topic},消息:{$message}"); return true; } catch (\Exception $e) { Log::error("MQTT 发布消息失败:" . $e->getMessage()); return false; } } /** * 订阅主题 * @param string|array $topics 主题(单个字符串或数组) * @param callable $callback 回调函数(处理收到的消息) * @param int $qos QoS 等级 */ public static function subscribe($topics, callable $callback, int $qos = null) { $client = self::connect(); if ($client === null) { return; } $qos = $qos ?? Config::get('mqtt.qos'); try { // 订阅主题 if (is_string($topics)) { $client->subscribe($topics, $callback, $qos); Log::info("MQTT 订阅主题成功:{$topics}"); } elseif (is_array($topics)) { foreach ($topics as $topic) { $client->subscribe($topic, $callback, $qos); Log::info("MQTT 订阅主题成功:{$topic}"); } } // 持续监听消息(阻塞模式,需在命令行运行) $client->loop(true); } catch (\Exception $e) { Log::error("MQTT 订阅失败:" . $e->getMessage()); throw new \Exception('MQTT 订阅失败:' . $e->getMessage()); } } // 关闭连接 public static function close() { if (self::$client !== null) { try { self::$client->disconnect(); Log::info('MQTT 连接已关闭'); } catch (\Exception $e) { Log::error('MQTT 关闭连接失败:' . $e->getMessage()); } self::$client = null; } } }
五、核心操作示例
1. 发布 MQTT 消息(控制器 / 业务层)
在任意控制器中调用工具类发布消息:
/app/api/controller/MqttPublish.php
<?php namespace app\api\controller; use app\BaseController; use think\facade\Db; use think\facade\Session; use app\common\lib\MqttClient;//Mqtt //Mqtt-发布 class MqttPublish extends BaseController { /** * 发布 MQTT 消息 * @return Json */ public function publish(){ // 主题和消息内容 $topic = 'wine_test'; $message = json_encode([ 'time' => date('Y-m-d H:i:s'), 'content' => 'Hello ThinkPHP6 + MQTT' ]); // 发布消息 $result = MqttClient::publish($topic, $message); if ($result) { //return returnData(1,'消息发布成功'); return json(['code' => 200, 'msg' => '消息发布成功']); } else { //return returnData(0,'消息发布失败'); return json(['code' => 500, 'msg' => '消息发布失败']); } } }
访问 http://你的域名/api/publish 即可触发消息发布。

2. 订阅 MQTT 消息(命令行脚本)
由于 MQTT 订阅是阻塞式的(需持续监听消息),需通过 ThinkPHP6 的命令行脚本实现:
步骤 1:创建命令行类
在 app/command 目录下创建
MqttSubscribe.php:app/command/MqttSubscribe.php
<?php // app/command/MqttSubscribe.php namespace app\command; use app\common\lib\MqttClient; use think\console\Command; use think\console\Input; use think\console\Output; class MqttSubscribe extends Command { // 配置命令 protected function configure() { $this->setName('mqtt:subscribe') ->setDescription('订阅 MQTT 主题并监听消息'); } // 执行命令 protected function execute(Input $input, Output $output) { $output->writeln('开始订阅 MQTT 主题...'); // 订阅主题(可配置多个) $topics = [ 'wine_test', ]; // 回调函数:处理收到的消息 $callback = function ($topic, $message) use ($output) { $output->writeln("\n收到消息:"); $output->writeln("主题:{$topic}"); $output->writeln("内容:{$message}"); }; // 开始订阅(阻塞运行) MqttClient::subscribe($topics, $callback); // 订阅结束后关闭连接 MqttClient::close(); $output->writeln('订阅结束'); } }
步骤 2:注册命令
在
config/console.php 中注册命令:<?php // +---------------------------------------------------------------------- // | 控制台配置 // +---------------------------------------------------------------------- return [ // 指令定义 'commands' => [ // 若存在类似如下配置,则表示已注册 'mqtt:subscribe' => app\command\MqttSubscribe::class,
],
];
步骤 3:运行订阅脚本
1.查询命令行是否已经注册:
php think list
- 若输出结果中无
mqtt相关的命名空间 / 命令,则说明该命令未注册 -
![image]()
项目根目录执行命令行:
php think mqtt:subscribe
有信息则成功
![]()
执行发布,看下订阅是否成功


浙公网安备 33010602011771号