<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); PHP_SAPI !== 'cli' && exit('脚本只能在命令行执行'); /** * 查询用户数据 * * @param int $uid 用户UID * @return array 用户数据 * @throws Swoole\ExitException */ function query(int $uid): array { // 从当前请求的协程上下文里取出PDO实例 $pdo = Swoole\Coroutine::getContext()['pdo']; // 构造SQL语句及参数 $query = 'SELECT `name`, `gender`, `birth` FROM `prefix_user` WHERE `uid` = ? LIMIT 1'; $args = [$uid]; // 预处理SQL语句 $statement = $pdo->prepare($query); $statement || throw new Swoole\ExitException('Prepare failed'); // 执行SQL语句 $result = $statement->execute($args); $result || throw new Swoole\ExitException('Execute failed'); $rows = $statement->fetchAll(PDO::FETCH_ASSOC); return $rows[0] ?? []; } Swoole\Coroutine::set(['hook_flags' => SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL]); // 一键协程化 Swoole\Coroutine\run(function () { $server = new Swoole\Coroutine\Http\Server('localhost', 9502, false); // 创建HTTP服务器 // 创建PDO配置对象 $config = new Swoole\Database\PDOConfig(); $config->withHost('localhost'); $config->withPort(3306); $config->withDbname('test_db'); $config->withCharset('utf8mb4'); $config->withUsername('********'); $config->withPassword('********'); // 创建PDO连接池,并指定连接池中PDO实例数量为64个(缺省值也是64) // $pool = new Swoole\Database\PDOPool($config, 64); $pool = new Swoole\Database\PDOPool($config, 3); // 测试PDO连接池没有PDO实例(只取出不放回) // 处理任意请求 $server->handle('/', function (Swoole\Http\Request $request, Swoole\Http\Response $response) use ($pool) { Swoole\Coroutine::create(static function () use ($request, $response, $pool): void { $method = $request->getMethod(); // 获取当前请求的请求方式 ($method !== 'POST' && $method !== 'GET') && throw new Swoole\ExitException('Error'); try { $pdo = $pool->get(); // 从PDO连接池里获取一个PDO实例(连接数据库失败会抛出异常) } catch (PDOException $e) { throw new Swoole\ExitException($e->getMessage()); } // 将PDO实例放回PDO连接池 defer(static function () use ($pool, $pdo) { $pool->put($pdo); echo 'PDO实例已放回PDO连接池' . PHP_EOL; }); // 把PDO实例放入本次请求的协程上下文,以便在其它地方使用PDO实例 Swoole\Coroutine::getContext()['pdo'] = $pdo; try { $row = query(9527); } catch (Swoole\ExitException) { $row = []; } if (isset($row['name'], $row['gender'], $row['birth'])) { $html = "俺叫{$row['name']}({$row['gender']}),出生于{$row['birth']}年。"; } else { $html = '_(:з」∠)_'; } $response->header('Content-Type', 'text/html; charset=utf-8'); $response->end($html); // 俺叫张三(男),出生于2003年。 }); }); $server->start(); // 启动HTTP服务器 }); //========== 总结 ==========// // 1、处理函数在最后必须将PDO实例放回PDO连接池,否则一旦PDO连接池里没有PDO实例将无法处理请求(表现为一直处于加载中)。 // 推荐做法是从PDO连接池里取出PDO实例后立即使用defer()函数将实例放回连接池,避免后面忘记写放回去代码。
Copyright © 2024 码农人生. All Rights Reserved