You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
4.8 KiB
116 lines
4.8 KiB
<?php
|
|
require_once __DIR__ . '/Config.php';
|
|
class Database {
|
|
private static $instance = null;
|
|
private $config;
|
|
private $connections = [];
|
|
private $inUse = [];
|
|
private $maxConnections = 10;
|
|
private $minConnections = 3;
|
|
private function __construct() {
|
|
$this->config = Config::getInstance();
|
|
$this->maxConnections = $this->config->get('database.max_connections', 10);
|
|
$this->minConnections = $this->config->get('database.min_connections', 3);
|
|
$this->initPool();
|
|
}
|
|
public static function getInstance() {
|
|
if (self::$instance === null) { self::$instance = new self(); }
|
|
return self::$instance;
|
|
}
|
|
private function initPool() {
|
|
for ($i = 0; $i < $this->minConnections; $i++) { $this->connections[] = $this->createConnection(); }
|
|
}
|
|
private function createConnection() {
|
|
$dbConfig = $this->config->get('database');
|
|
$host = $dbConfig['host'];
|
|
$port = $dbConfig['port'];
|
|
$database = $dbConfig['database'];
|
|
$username = $dbConfig['username'];
|
|
$password = $dbConfig['password'];
|
|
$charset = $dbConfig['charset'];
|
|
$dsn = "mysql:host={$host};port={$port};charset={$charset}";
|
|
$options = [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
PDO::ATTR_EMULATE_PREPARES => false,
|
|
PDO::ATTR_PERSISTENT => true
|
|
];
|
|
$pdo = new PDO($dsn, $username, $password, $options);
|
|
$pdo->exec("CREATE DATABASE IF NOT EXISTS `$database` CHARACTER SET $charset COLLATE {$dbConfig['collation']}");
|
|
$pdo->exec("USE `$database`");
|
|
return $pdo;
|
|
}
|
|
private function getConnection() {
|
|
if (count($this->connections) > 0) {
|
|
$pdo = array_pop($this->connections);
|
|
if (!$this->isValid($pdo)) { $pdo = $this->createConnection(); }
|
|
$this->inUse[] = $pdo;
|
|
return $pdo;
|
|
}
|
|
if (count($this->inUse) < $this->maxConnections) {
|
|
$pdo = $this->createConnection();
|
|
$this->inUse[] = $pdo;
|
|
return $pdo;
|
|
}
|
|
usleep(1000);
|
|
return $this->getConnection();
|
|
}
|
|
private function release($pdo) {
|
|
$key = array_search($pdo, $this->inUse);
|
|
if ($key !== false) {
|
|
unset($this->inUse[$key]);
|
|
if ($this->isValid($pdo)) { $this->connections[] = $pdo; }
|
|
}
|
|
}
|
|
private function isValid($pdo) {
|
|
try { $pdo->query("SELECT 1"); return true; } catch (PDOException $e) { return false; }
|
|
}
|
|
public function fetchAll($sql, $params = []) {
|
|
$pdo = $this->getConnection();
|
|
try { $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->fetchAll(); }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function fetchOne($sql, $params = []) {
|
|
$pdo = $this->getConnection();
|
|
try { $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->fetch(); }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function query($sql, $params = []) {
|
|
$pdo = $this->getConnection();
|
|
try { $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt; }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function insert($sql, $params = []) {
|
|
$pdo = $this->getConnection();
|
|
try { $stmt = $pdo->prepare($sql); $stmt->execute($params); return $pdo->lastInsertId(); }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function update($sql, $params = []) {
|
|
$pdo = $this->getConnection();
|
|
try { $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->rowCount(); }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function delete($sql, $params = []) {
|
|
$pdo = $this->getConnection();
|
|
try { $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->rowCount(); }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function beginTransaction() { $pdo = $this->getConnection(); $pdo->beginTransaction(); return $pdo; }
|
|
public function commit($pdo = null) { if ($pdo) { $pdo->commit(); $this->release($pdo); } }
|
|
public function rollback($pdo = null) { if ($pdo) { $pdo->rollBack(); $this->release($pdo); } }
|
|
public function isConnected() {
|
|
$pdo = $this->getConnection();
|
|
try { $pdo->query("SELECT 1"); return true; }
|
|
catch (PDOException $e) { return false; }
|
|
finally { $this->release($pdo); }
|
|
}
|
|
public function getPoolStatus() {
|
|
return [
|
|
'total_connections' => count($this->connections) + count($this->inUse),
|
|
'available_connections' => count($this->connections),
|
|
'in_use_connections' => count($this->inUse),
|
|
'max_connections' => $this->maxConnections
|
|
];
|
|
}
|
|
}
|