thinkphp中domain层边界应以业务职责为准,置于app/service或app/logic下,仅依赖repository接口、不耦合数据库实现;领域方法用业务语言命名,抛出领域异常,repository返回popo或数组,避免active record污染。

ThinkPHP 本身不内置 DDD 支持,Domain 层和 Repository 模式需手动分层实现;强行套用标准 DDD 术语(如 AggregateRoot、ValueObject)在 TP 中既无框架辅助,也容易变成“概念搬运”,反而加重维护负担。
TP 里怎么划 Domain 层边界?
别把 app/domain 当成必须目录。实际开发中,领域逻辑往往沉淀在 app/service 或 app/logic 下的类里——只要它只依赖 Repository 接口、不碰数据库连接或模型实例,就算履行了领域职责。
常见误操作:
- 在
Domain类里直接 newDb或调用think\Model::create() - 把表单校验、参数转换等应用层逻辑塞进 Domain 类
- 为每个字段建
ValueObject,但全程只用字符串传参
建议做法:
- 领域类构造函数只接收
Repository接口(如UserRepositoryInterface),不接收具体实现 - 方法名用业务语言,比如
transferBalance()而不是updateUserBalance() - 抛出领域异常(如
InsufficientBalanceException),而非DbException
Repository 接口与实现怎么配对才不翻车?
TP 的 think\Model 是 Active Record,天然带持久化能力,直接继承它写 Repository 实现会模糊分层——你得主动切断这种耦合。
关键控制点:
- 接口定义方法时,返回类型明确为
array、User(POPO)、Collection,绝不返回Query或Model实例 - 实现类里用
Db::name('user')或独立封装的查询构建器,绕过Model的 save() / create() 等副作用方法 - 避免在
Repository里做事务控制——那是Service或Application层的事
示例(接口):
interface UserRepositoryInterface
{
public function findById(int $id): ?User;
public function findByEmail(string $email): ?User;
public function save(User $user): void;
}
对应实现里,save() 应调用 Db::name('user')->insertOrReplace(...),而不是 $user->save()。
为什么泛型 Repository 在 TP 里要慎用?
TP 没有编译期泛型支持,所谓“泛型仓储”只是运行时传入类名字符串,容易掩盖类型错误,且无法约束字段合法性。
典型问题:
-
BaseRepository::update(123, ['status' => 'done'])—— ID 类型错、字段未校验,运行时才爆 - 所有实体共用一套分页逻辑,但
User需按注册时间排序,Order必须按订单号,硬塞进泛型方法里只能加 if 分支 - 联查场景(如用户+角色+权限)无法用泛型覆盖,最后还得写专用方法
更务实的做法:
- 按业务聚合建 Repository,比如
UserWithRoleRepository,内部组合多个基础查询 - 用 PHPDoc 注解补类型提示:
@param User $user,配合 IDE 和静态分析工具(如 PHPStan) - 把复用逻辑下沉到 trait 或工具类,而非强求接口统一
Repository 返回数组还是对象?
返回 array 最省事,但会丢失领域语义;返回 User 对象能封装行为,但要注意:TP 的 Model 不是贫血模型,它自带 save()、delete(),一不小心就又回到 Active Record 路线。
折中方案:
- 定义纯数据对象(POPO),只含 public 属性 + 构造器,不继承任何基类
- Repository 内部用
Db::query()或Db::name()->select()获取原始数组,再映射为 POPO - 需要行为的地方(如密码加密),由 Domain 类或专用 ValueObject 承担,不放进 Repository
这个边界一旦模糊,Repository 就开始悄悄接管业务逻辑,后面想抽离 ORM 或换存储时,改起来就不是改一个类的事了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











