应封装轻量级数据访问层:含pdo连接管理器(设异常模式、utf8mb4编码)、activerecord模型基类(预处理sql、主键智能判断)、链式查询构建器(支持多格式where、raw安全注入)及事务控制(自动连接复用、闭包回滚)。

要让PHP项目摆脱SQL拼接和重复数据库操作,又不引入全栈框架的臃肿,就得自己动手封装一个轻量级数据访问层——它得支持自动绑定、事务控制、简单查询链式调用,且不依赖任何第三方ORM。
定义基础PDO连接管理器
新建 src/Database/Connection.php,用静态工厂方法统一创建PDO实例,避免全局变量污染。
在构造函数中强制设置 【PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION】,否则 prepare 失败时静默吞掉错误,调试会卡死在空白页。
调用 PDO::setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8mb4") 确保中文不乱码,这步漏掉会导致客户姓名存成问号,修复成本远高于写时多敲两行。
实现ActiveRecord风格模型基类
创建 src/Model/Model.php,继承自 Connection,封装 insert、update、delete、find、findAll 等基础方法。
所有 SQL 构建逻辑必须走预处理语句,禁止字符串拼接字段名或表名——哪怕你100%确定输入可控,也得用白名单校验表名,否则一句 $table = $_GET['t'] 就能拖垮整个库。
在 save() 方法里判断主键是否存在:有值走 update,无值走 insert。这个判断不能只看 id === null,要兼容 UUID 或复合主键场景,所以得读取类的 $primaryKey 属性动态判断。
封装查询构建器(QueryBuilder)
方法一:链式调用语法糖
提供 select() → from() → where() → orderBy() → limit() 流式接口,每个方法返回 $this,最终调用 get() 或 first() 执行。
where() 必须支持三元组形式:where('status', '=', 'active') 和二元组形式:where(['status' => 'active']),后者用于批量条件,内部自动展开为 AND 连接。
方法二:原生SQL安全注入防护
提供 raw() 方法接收带占位符的SQL,如 "SELECT * FROM users WHERE created_at > ?",后续参数全部走 PDO::quote() 或 bindValue 绑定,绝不直接 sprintf 插入变量。
【注意:raw() 中的 ? 占位符数量必须与传入参数数组长度严格一致,否则 PDO 报错后不会提示缺失几个,只会抛出模糊的“invalid parameter number”】
事务与连接复用控制
第一步:在 Connection 类中添加 beginTransaction()、commit()、rollback() 方法,全部代理给底层 PDO 实例。
第二步:增加 inTransaction 属性,每次 begin 后设为 true,commit 或 rollback 后重置为 false。
第三步:在 query() 方法开头加判断:if ($this->inTransaction === false) { $this->connect(); },防止事务中途连接断开却没报错。
第四步:对外暴露 transaction() 静态方法,接收闭包回调,自动包裹 try-catch,失败时 rollback 并 re-throw 异常——这是唯一允许裸 throw 的地方,其他业务代码不准主动 throw PDOException。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











