插件窝 干货文章 ThinkPHP6框架下使用simps/mqtt连接阿里云物联网平台MQTT时如何解决“SwooleCoroutineClient::connect(): async-io must be used in PHP CLI mode”错误?

ThinkPHP6框架下使用simps/mqtt连接阿里云物联网平台MQTT时如何解决“SwooleCoroutineClient::connect(): async-io must be used in PHP CLI mode”错误?

Swoole mqtt 使用 Client 630    来源:    2025-03-13

在使用ThinkPHP6框架下通过simps/mqtt连接阿里云物联网平台MQTT时,遇到“SwooleCoroutineClient::connect(): async-io must be used in PHP CLI mode”错误,通常是因为Swoole的协程客户端(Swoole\Coroutine\Client)只能在PHP CLI模式下使用,而不能在FPM或Apache等Web服务器模式下使用。

解决方案

  1. 切换到CLI模式运行

    • 如果你是在Web请求中运行MQTT客户端代码,建议将MQTT客户端的连接和操作放到CLI模式下运行。可以通过编写一个命令行脚本来实现。
    • 在ThinkPHP6中,你可以创建一个自定义的命令行命令来执行MQTT连接和操作。

    步骤

    • app/command目录下创建一个新的命令文件,例如MqttCommand.php
    • 在命令文件中编写MQTT连接和操作的代码。
    • 通过命令行运行该命令。

    示例代码

    namespace app\command;
    
    use think\console\Command;
    use think\console\Input;
    use think\console\Output;
    use Simps\MQTT\Client;
    
    class MqttCommand extends Command
    {
       protected function configure()
       {
           $this->setName('mqtt:connect')->setDescription('Connect to MQTT');
       }
    
       protected function execute(Input $input, Output $output)
       {
           $config = [
               'host' => 'your-mqtt-endpoint',
               'port' => 1883,
               'username' => 'your-username',
               'password' => 'your-password',
               'client_id' => 'your-client-id',
           ];
    
           $client = new Client($config);
           $client->connect();
    
           // 订阅主题
           $client->subscribe('your/topic');
    
           // 处理消息
           $client->loop(function ($message) use ($output) {
               $output->writeln("Received message: " . $message['content']);
           });
       }
    }
    

    运行命令

    php think mqtt:connect
    
  2. 使用Swoole的HTTP服务器

    • 如果你需要在Web环境中使用Swoole的协程功能,可以考虑使用Swoole的HTTP服务器来替代传统的FPM或Apache。
    • 你可以通过Swoole的HTTP服务器来运行ThinkPHP6应用,这样可以在Web请求中使用Swoole的协程功能。

    步骤

    • 安装Swoole扩展。
    • 配置Swoole HTTP服务器来运行ThinkPHP6应用。

    示例代码

    use Swoole\Http\Server;
    use Swoole\Http\Request;
    use Swoole\Http\Response;
    
    $http = new Server("0.0.0.0", 9501);
    
    $http->on("start", function ($server) {
       echo "Swoole HTTP server is started at http://127.0.0.1:9501\n";
    });
    
    $http->on("request", function (Request $request, Response $response) {
       // 在这里处理ThinkPHP6的请求
       $response->header("Content-Type", "text/plain");
       $response->end("Hello World\n");
    });
    
    $http->start();
    
  3. 避免在Web请求中使用Swoole协程

    • 如果你无法切换到CLI模式或使用Swoole HTTP服务器,可以考虑避免在Web请求中使用Swoole的协程功能。可以使用其他MQTT客户端库,如php-mqtt/client,它不依赖于Swoole协程。

    示例代码

    use PhpMqtt\Client\MqttClient;
    use PhpMqtt\Client\ConnectionSettings;
    
    $server   = 'your-mqtt-endpoint';
    $port     = 1883;
    $clientId = 'your-client-id';
    $username = 'your-username';
    $password = 'your-password';
    
    $mqtt = new MqttClient($server, $port, $clientId);
    
    $connectionSettings = (new ConnectionSettings)
       ->setUsername($username)
       ->setPassword($password);
    
    $mqtt->connect($connectionSettings, true);
    
    $mqtt->subscribe('your/topic', function ($topic, $message) {
       echo "Received message on topic [$topic]: $message\n";
    });
    
    $mqtt->loop(true);
    

总结

  • 如果你需要在Web环境中使用Swoole协程,建议切换到CLI模式或使用Swoole HTTP服务器。
  • 如果无法切换,可以考虑使用其他不依赖Swoole协程的MQTT客户端库。

根据你的具体需求和环境选择合适的解决方案。