| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- <?php
- namespace BCJD;
- /**
- * Database - PDO 单例连接管理器
- *
- * 安全特性:
- * - 单例模式,避免重复连接
- * - 所有查询强制使用预处理语句
- * - 查询错误日志记录(不暴露细节给用户)
- * - 支持事务
- */
- class Database
- {
- private static ?Database $instance = null;
- private ?\PDO $pdo = null;
- private string $host;
- private int $port;
- private string $dbname;
- private string $user;
- private string $pass;
- private string $charset;
- private function __construct()
- {
- $this->host = DB_HOST;
- $this->port = DB_PORT;
- $this->dbname = DB_NAME;
- $this->user = DB_USER;
- $this->pass = DB_PASS;
- $this->charset = DB_CHARSET;
- }
- /** 禁止克隆 */
- private function __clone() {}
- public static function instance(): self
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
- return self::$instance;
- }
- /**
- * 获取 PDO 连接(惰性初始化)
- */
- public function getConnection(): \PDO
- {
- if ($this->pdo === null) {
- $dsn = sprintf(
- 'mysql:host=%s;port=%d;dbname=%s;charset=%s',
- $this->host, $this->port, $this->dbname, $this->charset
- );
- $this->pdo = new \PDO($dsn, $this->user, $this->pass, [
- \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
- \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
- \PDO::ATTR_EMULATE_PREPARES => false,
- \PDO::ATTR_STRINGIFY_FETCHES => false,
- ]);
- // 设置严格 SQL 模式
- $this->pdo->exec("SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'");
- }
- return $this->pdo;
- }
- /**
- * 执行查询返回所有行
- */
- public function fetchAll(string $sql, array $params = []): array
- {
- $stmt = $this->execute($sql, $params);
- return $stmt->fetchAll();
- }
- /**
- * 执行查询返回单行
- */
- public function fetchOne(string $sql, array $params = []): ?array
- {
- $stmt = $this->execute($sql, $params);
- $row = $stmt->fetch();
- return $row !== false ? $row : null;
- }
- /**
- * 执行查询返回单列值
- */
- public function fetchColumn(string $sql, array $params = []): mixed
- {
- $stmt = $this->execute($sql, $params);
- return $stmt->fetchColumn();
- }
- /**
- * 执行 INSERT/UPDATE/DELETE,返回受影响行数
- */
- public function execute(string $sql, array $params = []): \PDOStatement
- {
- $pdo = $this->getConnection();
- $stmt = $pdo->prepare($sql);
- $stmt->execute($params);
- return $stmt;
- }
- /**
- * 获取最后插入的 ID
- */
- public function lastInsertId(): string
- {
- return $this->getConnection()->lastInsertId();
- }
- /**
- * 事务封装
- */
- public function beginTransaction(): void
- {
- $this->getConnection()->beginTransaction();
- }
- public function commit(): void
- {
- $this->getConnection()->commit();
- }
- public function rollback(): void
- {
- $this->getConnection()->rollback();
- }
- /**
- * 不带数据库名连接(用于建库操作)
- */
- public static function rawConnection(): \PDO
- {
- $dsn = sprintf('mysql:host=%s;port=%d;charset=%s', DB_HOST, DB_PORT, DB_CHARSET);
- return new \PDO($dsn, DB_USER, DB_PASS, [
- \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
- ]);
- }
- /**
- * 销毁连接(用于重置)
- */
- public function close(): void
- {
- $this->pdo = null;
- self::$instance = null;
- }
- }
|