connection === null) { $this->connect(); } return $this->connection; } private function connect(): void { try { $dsn = sprintf( 'mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4', DB_HOST, DB_PORT, DB_NAME ); $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci" ]; $this->connection = new PDO($dsn, DB_USER, DB_PASS, $options); } catch (PDOException $e) { error_log('Database connection failed: ' . $e->getMessage()); throw new \Exception('Database connection failed'); } } public function query(string $sql, array $params = []): \PDOStatement { $stmt = $this->getConnection()->prepare($sql); $stmt->execute($params); return $stmt; } public function fetch(string $sql, array $params = []): ?array { $stmt = $this->query($sql, $params); $result = $stmt->fetch(); return $result ?: null; } public function fetchAll(string $sql, array $params = []): array { $stmt = $this->query($sql, $params); return $stmt->fetchAll(); } public function insert(string $table, array $data): int { $columns = implode(', ', array_keys($data)); $placeholders = ':' . implode(', :', array_keys($data)); $sql = "INSERT INTO {$table} ({$columns}) VALUES ({$placeholders})"; $this->query($sql, $data); return (int) $this->getConnection()->lastInsertId(); } public function update(string $table, array $data, string $where, array $whereParams = []): int { $setParts = []; foreach (array_keys($data) as $column) { $setParts[] = "{$column} = :{$column}"; } $setClause = implode(', ', $setParts); $sql = "UPDATE {$table} SET {$setClause} WHERE {$where}"; $params = array_merge($data, $whereParams); $stmt = $this->query($sql, $params); return $stmt->rowCount(); } public function delete(string $table, string $where, array $params = []): int { $sql = "DELETE FROM {$table} WHERE {$where}"; $stmt = $this->query($sql, $params); return $stmt->rowCount(); } public function beginTransaction(): bool { return $this->getConnection()->beginTransaction(); } public function commit(): bool { return $this->getConnection()->commit(); } public function rollback(): bool { return $this->getConnection()->rollback(); } public function inTransaction(): bool { return $this->getConnection()->inTransaction(); } public function quote(string $value): string { return $this->getConnection()->quote($value); } }