php中pdo单例模式确保请求内仅一个数据库连接,避免重复连接与事务不一致;通过私有构造、静态实例和全局访问点实现,支持配置隔离、错误处理及后续扩展。

PHP 中用 PDO 实现单例模式,核心是确保整个请求生命周期内只创建一个数据库连接实例,避免重复连接、节省资源、统一管理配置。
为什么用单例封装 PDO
直接 new PDO 每次都新建连接,可能造成连接数超限或事务不一致;单例能保证连接复用、配置集中、便于扩展(如添加日志、重连逻辑)。注意:PHP 的单例在一次 http 请求中有效,不是跨请求持久化。
基础单例类结构
以下是一个简洁可靠的 PDO 单例封装,支持 mysql,含基本错误处理和连接参数隔离:
class database { private static $instance = null; private $pdo; <pre class="brush:php;toolbar:false;">private function __construct($host, $dbname, $user, $pass, $charset = 'utf8mb4') { $dsn = "mysql:host={$host};dbname={$dbname};charset={$charset}"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; try { $this->pdo = new PDO($dsn, $user, $pass, $options); } catch (PDOException $e) { throw new RuntimeException("数据库连接失败: " . $e->getMessage()); } } public static function getInstance($host = 'localhost', $dbname = 'test', $user = 'root', $pass = '') { if (self::$instance === null) { self::$instance = new self($host, $dbname, $user, $pass); } return self::$instance; } public function getConnection() { return $this->pdo; } private function __clone() {} private function __wakeup() {}
}
立即学习“PHP免费学习笔记(深入)”;
如何使用这个单例
在项目中只需调用 getInstance 获取唯一连接对象,后续所有数据库操作都基于它:
- 获取连接:
$db = Database::getInstance('localhost', 'myapp', 'user', 'pass'); - 执行查询:
$stmt = $db->getConnection()->query("select * FROM users"); - 预处理语句:
$stmt = $db->getConnection()->prepare("INSERT INTO logs (msg) VALUES (?)"); $stmt->execute(['login']); - 事务控制也自然生效,因为共用同一个 PDO 实例:
$pdo = $db->getConnection(); $pdo->beginTransaction(); ... $pdo->commit();
可选增强点(按需添加)
实际项目中可进一步优化:
- 把连接参数移到配置文件或环境变量,避免硬编码
- 增加 ping 检测与自动重连逻辑(捕获 PDOException 后尝试重建连接)
- 封装常用方法如 queryOne、queryAll、insert、update,让业务层更简洁
- 配合依赖注入容器(如 PHP-DI)管理,替代硬编码调用 getInstance