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











