Files
zhamao-framework/src/ZM/Store/Database/DBPool.php

129 lines
4.0 KiB
PHP
Raw Normal View History

2022-08-21 16:08:20 +08:00
<?php
/** @noinspection PhpComposerExtensionStubsInspection */
declare(strict_types=1);
namespace ZM\Store\Database;
2022-08-21 16:08:20 +08:00
use OneBot\Driver\Driver;
use OneBot\Driver\Interfaces\PoolInterface;
use OneBot\Driver\Swoole\ObjectPool as SwooleObjectPool;
use OneBot\Driver\Swoole\SwooleDriver;
use OneBot\Driver\Workerman\ObjectPool as WorkermanObjectPool;
use OneBot\Driver\Workerman\WorkermanDriver;
use PDO;
use RuntimeException;
use ZM\Store\FileSystem;
2022-08-21 16:08:20 +08:00
class DBPool
2022-08-21 16:08:20 +08:00
{
/**
2022-08-21 16:25:05 +08:00
* @var array<string, SwooleObjectPool|WorkermanObjectPool> 连接池列表
2022-08-21 16:08:20 +08:00
*/
private static $pools = [];
/**
* 通过配置文件创建一个 MySQL 连接池
*
* @throws DBException
2022-08-21 16:08:20 +08:00
*/
public static function create(string $name, array $config)
{
$size = $config['pool_size'] ?? 64;
switch ($config['type']) {
case 'mysql':
$connect_str = 'mysql:host={host};port={port};dbname={dbname};charset={charset}';
$table = [
'{host}' => $config['host'],
'{port}' => $config['port'],
'{dbname}' => $config['dbname'],
'{charset}' => $config['charset'] ?? 'utf8mb4',
];
$connect_str = str_replace(array_keys($table), array_values($table), $connect_str);
$args = [$config['username'], $config['password'], $config['options'] ?? []];
self::checkMysqlExtension();
break;
case 'sqlite':
$connect_str = 'sqlite:{dbname}';
if (FileSystem::isRelativePath($config['dbname'])) {
$config['dbname'] = zm_dir(SOURCE_ROOT_DIR . '/' . $config['dbname']);
}
$table = [
'{dbname}' => $config['dbname'],
];
$args = [];
$connect_str = str_replace(array_keys($table), array_values($table), $connect_str);
break;
default:
throw new DBException('type ' . $config['type'] . ' not supported yet');
}
2022-08-21 16:08:20 +08:00
switch (Driver::getActiveDriverClass()) {
case WorkermanDriver::class:
self::$pools[$name] = new WorkermanObjectPool($size, PDO::class, $connect_str, ...$args);
2022-08-21 16:08:20 +08:00
break;
case SwooleDriver::class:
self::$pools[$name] = new SwooleObjectPool($size, PDO::class, $connect_str, ...$args);
2022-08-21 16:08:20 +08:00
}
}
/**
* 获取一个数据库连接池
*
2022-08-21 16:25:05 +08:00
* @param string $name 连接池名称
* @return SwooleObjectPool|WorkermanObjectPool
2022-08-21 16:08:20 +08:00
*/
2022-08-21 16:25:05 +08:00
public static function pool(string $name)
2022-08-21 16:08:20 +08:00
{
if (!isset(self::$pools[$name]) && count(self::$pools) !== 1) {
2022-08-21 16:08:20 +08:00
throw new RuntimeException("Pool {$name} not found");
}
return self::$pools[$name] ?? self::$pools[array_key_first(self::$pools)];
2022-08-21 16:08:20 +08:00
}
/**
* 获取所有数据库连接池
*
* @return PoolInterface[]
*/
public static function getAllPools(): array
{
return self::$pools;
}
/**
* 销毁数据库连接池
*
* @param string $name 数据库连接池名称
*/
public static function destroyPool(string $name)
{
unset(self::$pools[$name]);
}
/**
* 检查数据库启动必要的依赖扩展,如果不符合要求则抛出异常
*
* @throws DBException
2022-08-21 16:08:20 +08:00
*/
public static function checkMysqlExtension()
2022-08-21 16:08:20 +08:00
{
ob_start();
phpinfo(); // 这个phpinfo是有用的不能删除
$str = ob_get_clean();
$str = explode("\n", $str);
foreach ($str as $v) {
$v = trim($v);
if ($v == '') {
continue;
}
if (mb_strpos($v, 'API Extensions') === false) {
continue;
}
if (mb_strpos($v, 'pdo_mysql') === false) {
throw new DBException(zm_internal_errcode('E00028') . '未安装 mysqlnd php-mysql扩展。');
2022-08-21 16:08:20 +08:00
}
}
}
}