thinkphp 默认app目录结构不适用于复杂项目,因其导致业务逻辑与框架胶水混杂、领域边界模糊、测试复用困难;应改为app/domain(纯业务代码)和app/infra(框架适配层),并删除app/common,通过composer autoload配置psr-4映射,控制器迁移至app/infra/http,domain层严禁引入think类、上下文对象或硬编码路径。

ThinkPHP 的目录结构不是“设好了就一劳永逸”的,项目一复杂,app 目录下塞满控制器、模型、中间件、事件类,连自己都找不到 OrderService 是在 service 还是 logic 里——这不是你懒,是默认结构没对齐真实业务分层。
为什么不能直接用 ThinkPHP 默认的 app 目录结构?
ThinkPHP 6+ 默认把所有应用代码扔进 app,看似“扁平清晰”,实则掩盖了三个硬伤:
- 业务逻辑和框架胶水混在一起:
Controller和Middleware同级,但前者属于接口层,后者属于请求生命周期管理,语义层级不同 - 领域边界模糊:订单、用户、支付等模块的模型、服务、验证器散落在各子目录,重构或抽离模块时得全局搜索
order_ - 测试与复用困难:
app/common常被滥用为“万能工具箱”,结果ArrayHelper依赖了Db,导致单元测试无法脱离数据库运行
按领域分层:把 app 改成 app/domain + app/infra
不改框架入口,只重组织代码位置。核心是区分「什么业务在发生」和「怎么让业务跑起来」:
-
app/domain:只放纯业务代码,不含任何 ThinkPHP 类(如BaseModel、Request),例如app/domain/order/entity/Order.php、app/domain/order/service/OrderPaymentService.php -
app/infra:封装框架能力,比如app/infra/db/OrderModel.php(继承thinkModel)、app/infra/http/OrderController.php(调用domain层) - 必须删掉
app/common,工具函数按需下沉到app/infra/support(含框架依赖)或app/domain/shared(无依赖的值对象、枚举)
这样改完后,OrderController 只负责接收参数、返回 JSON,所有校验、状态流转、第三方调用都在 domain 层完成——哪怕哪天换 Laravel,只要重写 infra,业务代码几乎不用动。
路由与自动加载怎么适配新结构?
ThinkPHP 不会自动识别 app/domain,需要两处手动配置:
- 在
composer.json的autoload段补上 PSR-4 映射:"autoload": { "psr-4": { "app\domain\": "app/domain/", "app\infra\": "app/infra/" } }然后运行composer dump-autoload - 路由定义保持不变,但控制器类名要更新:原
appcontrollerOrderController→ 改为appinfrahttpOrderController,对应路由规则无需调整 - 注意命名空间别漏掉反斜杠:
use appdomainorderserviceOrderPaymentService;,少一个就会报Class not found
哪些文件坚决不能挪进 domain?
domain 目录是业务的“真空舱”,以下三类代码一旦进去,分层就失效:
- 任何带
think前缀的类:如thinkDb、thinkCache、thinkValidate—— 它们属于基础设施,只能出现在infra层 - 使用
$this->request或$this->app的方法:这些是容器或上下文对象,domain层应通过参数传入所需数据(如array $input),而非主动获取 - 硬编码路径或 URL:如
url('index/user')、__ROOT__/uploads/—— 这些应由infra层提供接口(如UrlGeneratorInterface::toUserPage()),domain只管“要跳转”,不管“怎么生成链接”
最常被忽略的是验证逻辑:把 Validate::make() 写在 domain 里,等于让业务规则依赖了框架的验证器实现。正确做法是定义 OrderCreationInput 数据对象,在 infra 层用 ThinkPHP 验证器校验后,再把干净数据传给 domain。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











