PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; try { self::$instance = new PDO($dsn, $username, $password, $options); } catch (PDOException $e) { // Log the exact error internally but hide sensitive DSN on production error_log("Database Connection Error: " . $e->getMessage()); throw new PDOException("Could not connect to the database. Check database settings."); } } return self::$instance; } /** * Shorthand execute statement with parameters * * @param string $sql * @param array $params * @return \PDOStatement */ public static function query(string $sql, array $params = []): \PDOStatement { $pdo = self::getConnection(); $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt; } /** * Retrieve all matching records */ public static function select(string $sql, array $params = []): array { return self::query($sql, $params)->fetchAll(); } /** * Retrieve single matching record */ public static function selectOne(string $sql, array $params = []) { return self::query($sql, $params)->fetch() ?: null; } /** * Insert record and return last inserted ID */ public static function insert(string $sql, array $params = []): string { $pdo = self::getConnection(); $stmt = $pdo->prepare($sql); $stmt->execute($params); return $pdo->lastInsertId(); } /** * Execute generic non-query SQL (Update/Delete) and return affected rows */ public static function execute(string $sql, array $params = []): int { return self::query($sql, $params)->rowCount(); } }