├── .gitignore ├── README.MD ├── composer.json └── src ├── Adapter ├── ConnectionFactory.php ├── Connectors │ ├── MySqlConnection.php │ ├── PostgresConnection.php │ ├── SQLiteConnection.php │ └── SqlServerConnection.php ├── Manager.php ├── Model.php └── QueryBuilder.php ├── PDOConfig.php ├── PDOPool.php ├── PoolManager.php └── Utils └── Context.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | ### 基于Swoole 封装的`连接池`以及适配了`illuminate/database` 2 | ###### 目前基于PDO规范 支持MySQL,SQL Server,Postgres和SQLite。 3 | 4 | #### 1. 引用本包 5 | ``` 6 | composer require itxiao6/database:dev-master 7 | ``` 8 | #### 2. 创建`配置`实例 9 | ```php 10 | /** 11 | * 创建配置 12 | */ 13 | (new \itxiao6\SwooleDatabase\PDOConfig())-> 14 | withDriver('mysql')-> // 驱动类型 15 | withHost('127.0.0.1')-> // 主机地址 16 | withDbname('test')-> // 数据库名 17 | withUsername('root')-> // 用户名 18 | withPassword('123456')-> // 密码 19 | withCharset('utf8mb4')-> // 字符集编码 20 | setConfig('default'); // 设置全局访问(默认为default) 21 | ``` 22 | #### 3. 设置 23 | ```php 24 | \itxiao6\SwooleDatabase\PoolManager::addPool(64,'default'); // 设置指定连接池尺寸(连接名称默认为 default) 25 | ``` 26 | 27 | #### 4. 使用协程环境模拟Swoole 的任务执行 28 | ```php 29 | /** 30 | * 开启协程(如果框架内已经开启可忽略) 31 | */ 32 | \Swoole\Runtime::enableCoroutine(); 33 | /** 34 | * 协程化IO钩子 35 | */ 36 | \Swoole\Coroutine::set(['hook_flags' => SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL]); 37 | /** 38 | * 记录开始时间 39 | */ 40 | $s = microtime(true); 41 | \Swoole\Coroutine\run(function () { 42 | /** 43 | * 循环创建协程(模拟HTTP 请求 执行任务) 44 | */ 45 | for ($i = 0; $i < 20; $i++) { 46 | \Swoole\Coroutine::create(function () { 47 | /** 48 | * 创建表 49 | */ 50 | // \itxiao6\SwooleDatabase\Manager::schema()->create('test',function(\Illuminate\Database\Schema\Blueprint $table){ 51 | // $table->increments('id'); 52 | // $table->string('name')->nullable()->default(1); 53 | // $table->timestamps(); 54 | // }); 55 | /** 56 | * 模型查询 57 | */ 58 | // $lists = \itxiao6\SwooleDatabase\Model::query()->first(); 59 | /** 60 | * Connection 直接查询 61 | */ 62 | $lists = \itxiao6\SwooleDatabase\Adapter\Manager::table('bd_live_plan')->first(); 63 | var_dump(boolval($lists)); 64 | /** 65 | * 协程销毁会自动归还连接(不需要手动处理) 66 | */ 67 | }); 68 | } 69 | }); 70 | echo '所有任务用了:' . (microtime(true) - $s) . '秒'; 71 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "itxiao6/database", 3 | "description": "The Swoole Pool Database package.", 4 | "license": "MIT", 5 | "homepage": "https://www.itxiao6.top", 6 | "keywords": [ 7 | "Laravel", 8 | "Swoole", 9 | "Databses", 10 | "Sql", 11 | "ORM" 12 | ], 13 | "authors": [ 14 | { 15 | "name": "itxiao6", 16 | "email": "itxiao6@qq.com" 17 | } 18 | ], 19 | "require": { 20 | "illuminate/database": "v8.8.0", 21 | "symfony/console": "^5.1" 22 | }, 23 | "require-dev": { 24 | "swoole/ide-helper": "@dev" 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "itxiao6\\SwooleDatabase\\": "src/" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Adapter/ConnectionFactory.php: -------------------------------------------------------------------------------- 1 | getDriver())) instanceof \Illuminate\Database\Connection)) { 33 | $pool = PoolManager::getPool($name); 34 | /** 35 | * 获取POD 36 | */ 37 | $pdo = $pool->get(); 38 | /** 39 | * 设置自动回收数据库连接 40 | */ 41 | Coroutine::defer(function () use ($name, $pdo) { 42 | /** 43 | * 归还当前协程内的连接 44 | */ 45 | PoolManager::getPool($name)->put($pdo); 46 | }); 47 | $connection = self::createConnection($pdo, $conifg); 48 | Context::put(Connection::class . $name . $conifg->getDriver(), $connection); 49 | } 50 | return $connection; 51 | } 52 | 53 | /** 54 | * @param $pod 55 | * @param PDOConfig $config 56 | * @return MySqlConnection|PostgresConnection|SQLiteConnection|SqlServerConnection 57 | */ 58 | public static function createConnection($pod, PDOConfig $config) 59 | { 60 | if (!in_array($config->getDriver(), ['mysql', 'pgsql', 'sqlite', 'sqlsrv'])) { 61 | throw new InvalidArgumentException('A driver must be specified.'); 62 | } 63 | 64 | switch ($config->getDriver()) { 65 | case 'mysql': 66 | return new MySqlConnection($pod, $config->getDbname(), $config->getTablePrefix(), []); 67 | case 'pgsql': 68 | return new PostgresConnection($pod, $config->getDbname(), $config->getTablePrefix(), []); 69 | case 'sqlite': 70 | return new SQLiteConnection($pod, $config->getDbname(), $config->getTablePrefix(), []); 71 | case 'sqlsrv': 72 | return new SqlServerConnection($pod, $config->getDbname(), $config->getTablePrefix(), []); 73 | } 74 | 75 | throw new InvalidArgumentException("Unsupported driver [{$config['driver']}]."); 76 | } 77 | } -------------------------------------------------------------------------------- /src/Adapter/Connectors/MySqlConnection.php: -------------------------------------------------------------------------------- 1 | setFetchMode($this->fetchMode); 24 | 25 | $this->event(new StatementPrepared( 26 | $this, $statement 27 | )); 28 | 29 | return $statement; 30 | } 31 | 32 | /** 33 | * 查询构造器 34 | * @return QueryBuilder 35 | */ 36 | public function query() 37 | { 38 | return new QueryBuilder( 39 | $this, $this->getQueryGrammar(), $this->getPostProcessor() 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /src/Adapter/Connectors/PostgresConnection.php: -------------------------------------------------------------------------------- 1 | table($table, $as); 27 | } 28 | /** 29 | * Get a schema builder instance. 30 | * 31 | * @param string|null $connection 32 | * @return \Illuminate\Database\Schema\Builder 33 | */ 34 | public static function schema($connection = null) 35 | { 36 | return static::connection($connection)->getSchemaBuilder(); 37 | } 38 | /** 39 | * Get a connection instance from the global manager. 40 | * 41 | * @param string|null $connection 42 | * @return \Illuminate\Database\Connection 43 | */ 44 | public static function connection($name = null) 45 | { 46 | if($name === null){ 47 | $name = 'default'; 48 | } 49 | return ConnectionFactory::getConnection($name); 50 | } 51 | /** 52 | * Dynamically pass methods to the default connection. 53 | * 54 | * @param string $method 55 | * @param array $parameters 56 | * @return mixed 57 | */ 58 | public static function __callStatic($method, $parameters) 59 | { 60 | return static::connection()->$method(...$parameters); 61 | } 62 | } -------------------------------------------------------------------------------- /src/Adapter/Model.php: -------------------------------------------------------------------------------- 1 | newQuery(); 30 | } 31 | 32 | /** 33 | * Get the database connection for the model. 34 | * 35 | * @return \Illuminate\Database\Connection 36 | */ 37 | public function getConnection() 38 | { 39 | return Manager::connection($this->getConnectionName()); 40 | } 41 | } -------------------------------------------------------------------------------- /src/Adapter/QueryBuilder.php: -------------------------------------------------------------------------------- 1 | tablePrefix; 111 | } 112 | 113 | /** 114 | * 设置表前缀 115 | * @param string $tablePrefix 116 | */ 117 | public function setTablePrefix($tablePrefix = '') 118 | { 119 | $this->tablePrefix = $tablePrefix; 120 | } 121 | 122 | /** 123 | * 获取编码 124 | * @return string 125 | */ 126 | public function getCharset(): string 127 | { 128 | return $this->charset; 129 | } 130 | 131 | /** 132 | * 获取数据库名称 133 | * @return string 134 | */ 135 | public function getDbname(): string 136 | { 137 | return $this->dbname; 138 | } 139 | 140 | /** 141 | * 获取驱动 142 | * @return string 143 | */ 144 | public function getDriver(): string 145 | { 146 | return $this->driver; 147 | } 148 | 149 | /** 150 | * 获取主机 151 | * @return string 152 | */ 153 | public function getHost(): string 154 | { 155 | return $this->host; 156 | } 157 | 158 | /** 159 | * 获取PDO参数 160 | * @return array 161 | */ 162 | public function getOptions(): array 163 | { 164 | return $this->options; 165 | } 166 | 167 | /** 168 | * 获取密码 169 | * @return string 170 | */ 171 | public function getPassword(): string 172 | { 173 | return $this->password; 174 | } 175 | 176 | /** 177 | * 获取端口 178 | * @return int 179 | */ 180 | public function getPort(): int 181 | { 182 | return $this->port; 183 | } 184 | 185 | /** 186 | * 获取 UnixSocket 187 | * @return string 188 | */ 189 | public function getUnixSocket(): string 190 | { 191 | return $this->unixSocket; 192 | } 193 | 194 | /** 195 | * 获取用户名 196 | * @return string 197 | */ 198 | public function getUsername(): string 199 | { 200 | return $this->username; 201 | } 202 | 203 | /** 204 | * 是否存在UnixSocket 205 | * @return bool 206 | */ 207 | public function hasUnixSocket(): bool 208 | { 209 | return isset($this->unixSocket); 210 | } 211 | 212 | /** 213 | * 设置编码 214 | * @param string $charset 215 | * @return $this 216 | */ 217 | public function withCharset(string $charset) 218 | { 219 | $this->charset = $charset; 220 | return $this; 221 | } 222 | 223 | /** 224 | * 设置数据库名称 225 | * @param string $dbname 226 | * @return $this 227 | */ 228 | public function withDbname(string $dbname) 229 | { 230 | $this->dbname = $dbname; 231 | return $this; 232 | } 233 | 234 | /** 235 | * 设置驱动 236 | * @param string $driver 237 | * @return $this 238 | */ 239 | public function withDriver(string $driver) 240 | { 241 | $this->driver = $driver; 242 | return $this; 243 | } 244 | 245 | /** 246 | * 设置主机 247 | * @param $host 248 | * @return $this 249 | */ 250 | public function withHost($host) 251 | { 252 | $this->host = $host; 253 | return $this; 254 | } 255 | 256 | /** 257 | * 设置PDO链接参数 258 | * @param array $options 259 | * @return $this 260 | */ 261 | public function withOptions(array $options) 262 | { 263 | $this->options = $options; 264 | return $this; 265 | } 266 | 267 | /** 268 | * 设置密码 269 | * @param string $password 270 | * @return $this 271 | */ 272 | public function withPassword(string $password) 273 | { 274 | $this->password = $password; 275 | return $this; 276 | } 277 | 278 | /** 279 | * 设置端口 280 | * @param int $port 281 | * @return $this 282 | */ 283 | public function withPort(int $port) 284 | { 285 | $this->port = $port; 286 | return $this; 287 | } 288 | 289 | /** 290 | * 设置UnixSocket 291 | * @param string|null $unixSocket 292 | * @return $this 293 | */ 294 | public function withUnixSocket(?string $unixSocket) 295 | { 296 | $this->unixSocket = $unixSocket; 297 | return $this; 298 | } 299 | 300 | /** 301 | * 设置用户名 302 | * @param string $username 303 | * @return $this 304 | */ 305 | public function withUsername(string $username) 306 | { 307 | $this->username = $username; 308 | return $this; 309 | } 310 | 311 | /** 312 | * 获取可用的驱动 313 | * @return string[] 314 | */ 315 | public static function getAvailableDrivers() 316 | { 317 | return [ 318 | self::DRIVER_MYSQL, 319 | ]; 320 | } 321 | 322 | /** 323 | * 设置编码 324 | * @param string $charset 325 | */ 326 | public function setCharset(string $charset): void 327 | { 328 | $this->charset = $charset; 329 | } 330 | 331 | /** 332 | * 设置数据库名称 333 | * @param string $dbname 334 | */ 335 | public function setDbname(string $dbname): void 336 | { 337 | $this->dbname = $dbname; 338 | } 339 | 340 | /** 341 | * 设置驱动 342 | * @param string $driver 343 | */ 344 | public function setDriver(string $driver): void 345 | { 346 | $this->driver = $driver; 347 | } 348 | 349 | /** 350 | * 设置主机 351 | * @param string $host 352 | */ 353 | public function setHost(string $host): void 354 | { 355 | $this->host = $host; 356 | } 357 | 358 | /** 359 | * 设置PDO链接参数 360 | * @param array $options 361 | */ 362 | public function setOptions(array $options): void 363 | { 364 | $this->options = $options; 365 | } 366 | 367 | /** 368 | * 设置密码 369 | * @param string $password 370 | */ 371 | public function setPassword(string $password): void 372 | { 373 | $this->password = $password; 374 | } 375 | 376 | /** 377 | * 设置端口 378 | * @param int $port 379 | */ 380 | public function setPort(int $port): void 381 | { 382 | $this->port = $port; 383 | } 384 | 385 | /** 386 | * 设置unixSocket 387 | * @param string|null $unixSocket 388 | */ 389 | public function setUnixSocket(?string $unixSocket): void 390 | { 391 | $this->unixSocket = $unixSocket; 392 | } 393 | 394 | /** 395 | * 设置用户名 396 | * @param string $username 397 | */ 398 | public function setUsername(string $username): void 399 | { 400 | $this->username = $username; 401 | } 402 | } -------------------------------------------------------------------------------- /src/PDOPool.php: -------------------------------------------------------------------------------- 1 | config = $config; 30 | parent::__construct(function () { 31 | return new PDO( 32 | "{$this->config->getDriver()}:" . 33 | ( 34 | $this->config->hasUnixSocket() ? 35 | "unix_socket={$this->config->getUnixSocket()};" : 36 | "host={$this->config->getHost()};" . "port={$this->config->getPort()};" 37 | ) . 38 | "dbname={$this->config->getDbname()};" . 39 | "charset={$this->config->getCharset()}", 40 | $this->config->getUsername(), 41 | $this->config->getPassword(), 42 | $this->config->getOptions() 43 | ); 44 | }, $size, PDOProxy::class); 45 | } 46 | } -------------------------------------------------------------------------------- /src/PoolManager.php: -------------------------------------------------------------------------------- 1 | put($item['pdo']); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/Utils/Context.php: -------------------------------------------------------------------------------- 1 | 0) { 31 | self::$pool[$cid][$key] = $item; 32 | } 33 | } 34 | 35 | /** 36 | * @return bool 37 | */ 38 | static function inCoroutine(){ 39 | return Coroutine::getuid()>0; 40 | } 41 | 42 | static function delete($key = null) 43 | { 44 | $cid = Coroutine::getuid(); 45 | if ($cid > 0) { 46 | if ($key) { 47 | unset(self::$pool[$cid][$key]); 48 | } else { 49 | unset(self::$pool[$cid]); 50 | } 51 | } 52 | } 53 | } --------------------------------------------------------------------------------