Files
freeshop/includes/DbDriver.php
T
2026-08-14 10:55:06 +08:00

208 lines
5.4 KiB
PHP

<?php
/**
* 数据库驱动抽象层
*
* 支持 MySQL (PDO/MySQL) 和 SQLite3 (PDO/SQLite)。
* 在 config.php 中通过 DB_DRIVER 配置:'mysql' 或 'sqlite'
*
* 安装时用户可选择驱动:
* - MySQL: 需要配置 DB_HOST / DB_PORT / DB_NAME / DB_USER / DB_PASS
* - SQLite: 需要配置 DB_SQLITE_PATH(数据库文件路径)
*/
if (!defined('IN_APP')) exit('Forbidden');
class DbDriver
{
/** @var PDO|null 当前连接 */
private static $pdo = null;
/** @var string 驱动类型 'mysql' | 'sqlite' */
private static $driver = 'mysql';
/**
* 获取 PDO 实例(单例)。
* @return PDO
*/
public static function connect()
{
if (self::$pdo !== null) return self::$pdo;
self::$driver = defined('DB_DRIVER') ? DB_DRIVER : 'mysql';
try {
if (self::$driver === 'sqlite') {
$path = defined('DB_SQLITE_PATH') ? DB_SQLITE_PATH : (__DIR__ . '/../data/database.sqlite');
$dir = dirname($path);
if (!is_dir($dir)) mkdir($dir, 0755, true);
self::$pdo = new PDO('sqlite:' . $path);
self::$pdo->exec('PRAGMA journal_mode=WAL');
self::$pdo->exec('PRAGMA foreign_keys=ON');
} else {
// MySQL(默认)
$host = defined('DB_HOST') ? DB_HOST : 'localhost';
$port = defined('DB_PORT') ? DB_PORT : '3306';
$name = defined('DB_NAME') ? DB_NAME : 'mall';
$user = defined('DB_USER') ? DB_USER : 'root';
$pass = defined('DB_PASS') ? DB_PASS : '';
$charset = 'utf8mb4';
$dsn = "mysql:host={$host};port={$port};dbname={$name};charset={$charset}";
self::$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
}
} catch (PDOException $e) {
if (defined('DEBUG') && DEBUG) {
throw $e;
}
die('数据库连接失败,请检查配置。' . (DEBUG ? ' [' . $e->getMessage() . ']' : ''));
}
return self::$pdo;
}
/**
* 获取当前驱动类型。
*/
public static function getDriver()
{
return self::$driver;
}
/**
* 是否为 SQLite。
*/
public static function isSqlite()
{
return self::$driver === 'sqlite';
}
/**
* 是否为 MySQL。
*/
public static function isMysql()
{
return self::$driver === 'mysql';
}
/**
* 获取原始 PDO 对象。
*/
public static function pdo()
{
return self::connect();
}
/**
* 关闭连接。
*/
public static function close()
{
self::$pdo = null;
}
/**
* 执行 SQL 并返回影响行数。
*/
public static function exec($sql)
{
return self::connect()->exec($sql);
}
/**
* 查询并返回全部行。
*/
public static function queryAll($sql, $params = [])
{
$stmt = self::connect()->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
/**
* 查询并返回一行。
*/
public static function queryOne($sql, $params = [])
{
$stmt = self::connect()->prepare($sql);
$stmt->execute($params);
return $stmt->fetch();
}
/**
* 查询并返回单个值。
*/
public static function queryScalar($sql, $params = [])
{
$row = self::queryOne($sql, $params);
return $row ? reset($row) : null;
}
/**
* 获取最后插入 ID。
*/
public static function lastInsertId()
{
return self::connect()->lastInsertId();
}
/**
* 在事务中执行回调。
*/
public static function transaction(callable $callback)
{
$pdo = self::connect();
try {
$pdo->beginTransaction();
$result = $callback($pdo);
$pdo->commit();
return $result;
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
}
/**
* 检查表是否存在。
*/
public static function tableExists($table)
{
if (self::isSqlite()) {
$name = str_replace(self::getPrefix(), '', $table);
return self::queryScalar(
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?",
[$name]
) > 0;
} else {
$db = defined('DB_NAME') ? DB_NAME : '';
return self::queryScalar(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=? AND table_name=?",
[$db, $table]
) > 0;
}
}
/**
* 获取表前缀。
*/
public static function getPrefix()
{
return defined('DB_PREFIX') ? DB_PREFIX : '';
}
/**
* 列出所有表名。
*/
public static function listTables()
{
if (self::isSqlite()) {
return self::queryAll("SELECT name FROM sqlite_master WHERE type='table'");
} else {
$db = defined('DB_NAME') ? DB_NAME : '';
return self::queryAll("SELECT table_name AS name FROM information_schema.tables WHERE table_schema=?", [$db]);
}
}
}