PHP 数据库访问的分层设计实践

5次阅读

php数据库访问采用分层设计,核心是剥离数据操作逻辑:dal层封装数据库交互细节并统一异常处理,领域模型层定义纯数据结构,业务逻辑层协调规则执行,依赖注入实现松耦合。

PHP 数据库访问的分层设计实践

PHP 数据库访问采用分层设计,核心是把数据操作逻辑从业务代码中剥离出来,让各层职责清晰、便于测试和维护。重点在于隔离变化——数据库驱动切换、sql 调整、业务规则变更,都不该牵一发而动全身。

数据访问层(DAL):只管“怎么查、怎么存”

这一层封装所有与数据库交互的细节,不处理业务含义。典型做法是为每张核心表或业务实体定义一个数据访问类(如 UserRepositoryOrderMapper),提供标准化方法:
find($id)findAll()save($entity)delete($id)
– 方法内部使用 pdo 或 Doctrine DBAL 等底层驱动,统一处理连接、预处理、异常转换(如把 PDOException 转为自定义 DataAccessException)
– 不暴露 SQL 字符串或 Statement 对象给上层,也不做字段映射逻辑(那是 ORM 或 DTO 层的事)

领域模型层(Entity/DTO):定义“数据长什么样”

用简单 PHP 类描述业务概念,比如 User 类包含 id、name、email 等属性和基础行为(如 isActive())。关键点:
– 类中不含数据库操作代码,也不依赖 PDO 或任何扩展
– 可以是贫血模型(纯数据载体),也可以带少量业务方法(如密码校验)
– 若需兼容不同数据源(如 API + DB),可用 DTO 分离传输结构,避免 Entity 被污染

业务逻辑层(Service):专注“做什么、为什么做”

这是协调者,调用 DAL 获取数据,对 Entity 执行业务规则,再决定是否保存或通知其他模块。例如:
UserRegistrationService::register(Array $input) 会先校验邮箱格式、检查用户名是否已存在(调用 UserRepository::findByEmail()),再创建 User 实体、加密密码、调用 UserRepository::save()
– 不拼接 SQL,不处理事务边界(由框架或显式 begin/commit 控制),也不做 http 响应组装
– 服务方法应小粒度、可组合,方便单元测试时 mock DAL

配置与依赖注入:让层之间松耦合

避免 new UserRepository() 这类硬编码。用容器管理依赖:
– 在启动时绑定 UserRepositoryInterface → MysqlUserRepository(或 SqliteUserRepository)
– Service 构造函数声明接口依赖,运行时自动注入具体实现
– 数据库连接参数(host、dbname 等)从环境变量或配置文件加载,不写死在 DAL 类里
– 可配合 PSR-4 自动加载,目录结构按层划分(如 src/Infrastructure/Persistence/、src/Domain/Model/、src/Application/Service/)

text=ZqhQzanResources