PHP项目目录结构怎么规划?一份面向现代Web开发的黄金标准指南
目录导读
- 为什么目录结构决定了项目的生死
- 经典分层架构:MVC不是银弹,但它是起点
- 现代PHP项目目录规划实战(基于Composer + PSR-4)
- 模块化 vs 单体:如何根据业务规模选择
- 常见反模式:这些坑90%的开发者都踩过
- 问答环节:解决你最后的5个疑惑
- 从今天起重构你的项目骨架
为什么目录结构决定了项目的生死

在PHP开发中,目录结构往往被视为“低级问题”,但谷歌和必应的爬虫对代码可读性毫无兴趣,而真正的风险在于团队协作成本和后期维护噩梦,一个混乱的目录会让新成员花费3天才能找到修改一个接口的位置,而规范的目录能让CI/CD流程、单元测试、依赖管理无缝衔接,更关键的是,PSR-4自动加载规范(PHP-FIG制定)要求目录结构与命名空间严格对应,这直接决定了你的代码能否被Composer生态高效拉取。
经典分层架构:MVC不是银弹,但它是起点
大多数PHP框架(Laravel、Symfony、CodeIgniter)默认采用MVC,但目录划分绝不仅仅是将Controller、Model、View三个文件夹堆在一起,核心在于依赖方向:Controller依赖Service,Service依赖Repository,Repository依赖Model,一个规范的目录必须体现这种层级:
project/
├── app/
│ ├── Http/ # 控制器、中间件、请求表单
│ ├── Services/ # 业务逻辑层(核心)
│ ├── Repositories/ # 数据访问层
│ └── Models/ # Eloquent/Doctrine实体
├── config/ # 环境配置
├── database/ # 迁移、填充、工厂
├── routes/ # 路由定义
├── resources/ # 视图、语言包、静态资源
├── tests/ # 单元/功能测试
└── public/ # Web根目录(唯一对外暴露)
现代PHP项目目录规划实战(基于Composer + PSR-4)
以Laravel 11 + PHP 8.3为例,推荐更细粒度的切割:
- Domain层(业务核心):
app/Domain/Order/Entities/、Events/、Exceptions/,将订单逻辑放入独立文件夹,而不是堆在Models里。 - Application层:
app/Application/UseCases/存放“生成订单”或“取消订单”这类用例类,每个类仅负责一个动作。 - Infrastructure层:
app/Infrastructure/Persistence/负责外部API、缓存、数据库实现。
关键优化技巧:在composer.json中明确映射命名空间:
"autoload": {
"psr-4": {
"App\\Domain\\": "app/Domain/",
"App\\Application\\": "app/Application/"
}
}
这样,new App\Domain\Order\OrderEntity会自动寻址到对应文件,部署时执行composer dump-autoload -o即可生成优化加载器。
模块化 vs 单体:如何根据业务规模选择
- 小团队/快速原型:按技术层划分即可,但必须在
app/下保留Services独立层,否则业务逻辑会泄漏到控制器里。 - 中大型项目:强烈推荐模块化DDD,示例:
src/Modules/Billing/,内含Application/、Domain/、Infrastructure/、UI/四个子目录,这种结构让多个团队可以并行开发不同模块,且模块间通过接口通信,降低耦合。
常见反模式:这些坑90%的开发者都踩过
- ❌ 把所有模型放在一个
Models文件夹:当项目有300个表时,你会疯掉。 - ❌ 在控制器里写SQL查询:这破坏了分层,导致无法单元测试。
- ❌ 直接使用
/lib或/vendor存放业务代码:vendor只应放第三方依赖,业务代码扔进去会因composer更新被覆盖。 - ❌ 忽略
tests目录的对应结构:测试必须与应用目录镜像,否则无法自动化定位测试类。
问答环节:解决你最后的5个疑惑
-
Q1:每个目录都需要
index.php吗?
A:不需要,只有public/需有入口文件,其他目录建议放置.gitkeep或README.md,防止空目录被版本控制系统忽略。 -
Q2:我可以用
app/而不是src/吗?
A:可以,但必须与composer.json中的PSR-4映射保持一致,框架默认app/,但src/更中立,适合非框架核心代码。 -
Q3:配置文件应该放哪里?
A:config/目录,但禁止将密钥、数据库密码写入文件,推荐使用环境变量(.env)并在.gitignore里排除。 -
Q4:静态资源(CSS/JS)何时放在
public/外?
A:当需要经过压缩、版本哈希时,可放在resources/assets/,由前端构建工具(如Vite、Webpack)编译后输出至public/build/。 -
Q5:如何在现有项目中安全重构目录?
A:一次只移动一个命名空间,先修改composer.json,执行composer dump-autoload,运行完整测试,若没有测试……那就先写测试,再重构!
从今天起重构你的项目骨架
目录结构不是艺术,而是工程纪律,它决定了你的代码是“一次性创作”还是“可长期演进的资产”,请打开你的终端,执行mkdir -p app/Domain app/Application app/Infrastructure tests/Domain,然后给你的业务逻辑安个家。好的目录让你在凌晨3点被叫醒处理紧急事故时,能5分钟内定位问题——这就是它存在的唯一意义。
(本文基于PSR-4规范、Laravel最佳实践及十余年PHP社区经验综合撰写,适用于任何现代PHP框架。)