php pdo 代码重构核心是提升安全性、可维护性与可测试性,需分离关注点、统一异常处理、避免硬编码,采用依赖注入传递 pdo 实例,强制使用预处理语句与参数绑定,并封装查询逻辑到 repository/dao 方法中。

PHP PDO 代码重构不是重写 SQL,而是让数据库交互更安全、可维护、可测试。核心是分离关注点、统一错误处理、避免硬编码,并为扩展留余地。
用依赖注入替代全局 PDO 实例
直接 new PDO() 或使用全局变量会让测试困难、耦合度高。应将 PDO 实例作为依赖传入类中,或通过容器管理。
- 构造函数注入最清晰:class UserRepository { private PDO $pdo; public function __construct(PDO $pdo) { $this->pdo = $pdo; } }
- 避免在业务逻辑里创建 PDO 连接——连接应由启动层(如 index.php 或 DI 容器)初始化并传递
- 若需多个数据源(如主从),可注入不同命名的 PDO 实例,或封装为 ConnectionManager 类
用预处理语句 + 命名参数代替字符串拼接
所有用户输入必须走参数绑定,命名参数比问号占位符更易读、易复用、顺序不敏感。
- ✅ 正确:
$stmt = $pdo->prepare("SELECT * FROM users WHERE status = :status AND role IN (:roles)");<br>$stmt->execute(['status' => 'active', 'roles' => ['admin', 'editor']]); - ❌ 危险:
"WHERE id = " . $_GET['id']或"WHERE name LIKE '%" . $_POST['q'] . "%'" - 注意:IN 子句不能直接绑定数组,需动态生成占位符,例如
str_repeat('?,', count($ids) - 1) . '?',再用 array_values($ids) 绑定
封装查询逻辑到专用方法,避免裸 SQL 散布
把常用查询提取为 Repository 或 DAO 方法,隐藏 SQL 细节,统一返回结构(如对象、关联数组、值列表)。
立即学习“PHP免费学习笔记(深入)”;
- 例如:getUserById(int $id): ?User,而不是在控制器里写 prepare+execute+fetch
- 复杂查询可拆解为私有方法(如 buildWhereClause(), applyPagination()),保持主方法语义清晰
- 返回值类型明确:用 PDO::FETCH_CLASS、PDO::FETCH_ASSOC 或自定义 fetchAllAsObjects() 封装,避免到处写 fetchAll()
统一异常处理与日志记录
PDO 默认不抛异常,需显式设置;异常不应被静默吞掉,关键操作要记录上下文。
- 初始化时启用异常模式:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - 捕获 PDOException 时,记录 SQL、参数、错误码($e->getCode())、消息($e->getMessage()),但不要暴露给前端
- 对重复键、外键冲突等预期异常,用具体 catch 分支处理(如“用户名已存在”),而非全用通用错误页
不复杂但容易忽略:每次重构后运行一次查询性能分析(如 EXPLAIN),确认索引仍生效;同时检查事务边界是否清晰,避免长事务或意外自动提交。











