error = ""; $this->name = $name; if (is_array($config)) { $this->parseArray($config); } else { if (is_dir($config)) { $this->loadEnv($config); } } $this->initPdo(); } private function parseArray($config) { try { $key = (strtolower(trim($this->name))); $this->type = isset($config[$key]["TYPE"]) ? $config[$key]["TYPE"] : null; $this->user = isset($config[$key]["USER"]) ? $config[$key]["USER"] : null; $this->host = isset($config[$key]["HOST"]) ? $config[$key]["HOST"] : null; $this->password = isset($config[$key]["PASSWORD"]) ? $config[$key]["PASSWORD"] : null; $this->database = isset($config[$key]["DATABASE"]) ? $config[$key]["DATABASE"] : null; $this->port = isset($config[$key]["PORT"]) ? $config[$key]["PORT"] : null; } catch (\Throwable $th) { $this->error = $th->getMessage(); } } private function loadEnv($dir) { try { $dotenv = Dotenv::createImmutable($dir); $dotenv->load(); } catch (\Throwable $th) { $this->error = $th->getMessage(); } $this->parseEnv(); } private function parseEnv() { try { $key = (strtoupper(trim($this->name))); $this->type = isset($_ENV[$this->getKey("TYPE", $key)]) ? $_ENV[$this->getKey("TYPE", $key)] : null; $this->user = isset($_ENV[$this->getKey("USER", $key)]) ? $_ENV[$this->getKey("USER", $key)] : null; $this->host = isset($_ENV[$this->getKey("HOST", $key)]) ? $_ENV[$this->getKey("HOST", $key)] : null; $this->password = isset($_ENV[$this->getKey("PASSWORD", $key)]) ? $_ENV[$this->getKey("PASSWORD", $key)] : null; $this->database = isset($_ENV[$this->getKey("DATABASE", $key)]) ? $_ENV[$this->getKey("DATABASE", $key)] : null; $this->port = isset($_ENV[$this->getKey("PORT", $key)]) ? $_ENV[$this->getKey("PORT", $key)] : null; } catch (\Throwable $th) { $this->error = $th->getMessage(); } } private function getKey(string $type, string $name): string { return "DB_" . $name . "_" . $type; } private function initPdo() { $this->getConnString(); $this->pdo = new PDO($this->connstring, $this->user, $this->password); $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } private function bindParams(PDOStatement $stmt, array $data): PDOStatement { $iParams = 1; foreach ($data as $value) { if ($value instanceof \DateTime) { $stmt->bindValue($iParams, $value->format('Y-m-d H:i:s'), PDO::PARAM_STR); } else { switch (gettype($value)) { case 'integer': $stmt->bindValue($iParams, $value, PDO::PARAM_INT); break; case 'datetime': $stmt->bindValue($iParams, $value, PDO::PARAM_STR); break; case 'boolean': $stmt->bindValue($iParams, $value, PDO::PARAM_BOOL); break; case 'NULL': $stmt->bindValue($iParams, $value, PDO::PARAM_NULL); break; default: $stmt->bindValue($iParams, $value, PDO::PARAM_STR); } } $iParams++; } return $stmt; } private function getConnString() { $this->connstring = match ($this->type) { "mysql" => "mysql:host=" . $this->host . ":" . $this->port . ";dbname=" . $this->database, "sqlite" => "sqlite:" . $this->database, }; } public function executeRawQuery(string $rawquery): bool { $stmt = $this->pdo->prepare($rawquery); return $stmt->execute(); } public function getSelectQuery(Query $query, $fetchmode = PDO::FETCH_ASSOC): mixed { $stmt = $this->pdo->prepare($query->getQuery()); $stmt = $this->bindParams($stmt, $query->getData()); EventDispatcher::emit("on.query", $query); $stmt->execute(); return $stmt->fetchAll($fetchmode); } public function updateQuery(Query $query): bool { $stmt = $this->pdo->prepare($query->getQuery()); $stmt = $this->bindParams($stmt, $query->getData()); EventDispatcher::emit("on.query", $query); return $stmt->execute(); } public function insertQuery(Query $query): mixed { $stmt = $this->pdo->prepare($query->getQuery()); $stmt = $this->bindParams($stmt, $query->getData()); EventDispatcher::emit("on.query", $query); $ok = $stmt->execute(); if ($ok) { return $this->pdo->lastInsertId(); } else { return false; } } public function beginTransaction(): bool { if ($this->pdo) { return $this->pdo->beginTransaction(); } return false; } public function commit(): bool { if ($this->pdo) { return $this->pdo->commit(); } return false; } public function rollback(): bool { if ($this->pdo) { return $this->pdo->rollBack(); } return false; } public static function init($config, array $connections = ["default"]) { self::fillInstances($config, $connections); return self::getInstance(); } private static function fillInstances($config, array $connections) { foreach ($connections as $connection) { if (!isset(self::$instances[$connection])) { self::$instances[$connection] = new Connection($connection, $config); } } } public static function getInstance($connection = "") { if ($connection == "" && count(self::$instances) > 0) { $connection = array_keys(self::$instances)[0]; } if (isset(self::$instances[$connection])) { $instance = self::$instances[$connection]; if ($instance instanceof Connection) { return self::$instances[$connection]; } } throw new \Exception("Unknown connection"); } public function getError() { return $this->error; } public function getPdo() { return $this->pdo; } public function getDriverType() { return $this->type; } }