本文目录导读:

这是一个非常经典且重要的问题,合理的目录结构是项目可维护性、可扩展性和团队协作的基础。
PHP项目的目录结构没有绝对的“唯一标准”,但业界有一些经过大量实践检验的最佳实践模式,这里我会介绍几种最常见、最推荐的方案,并提供适用场景分析。
核心原则
在开始之前,请记住这几个核心原则:
- 约定优于配置:团队成员遵循统一的约定,减少沟通成本。
- 关注点分离:业务逻辑、数据访问、视图展示、公共配置要分开。
- 入口安全:Web 根目录只放置唯一的入口文件和静态资源,业务代码放在根目录之外,无法被直接访问。
- 可扩展性:便于后期添加新功能或模块。
基于框架的标准结构(最推荐)
这是基于现代框架(如 Laravel、Symfony、ThinkPHP、Yii2)的终极进化版。这是最推荐的方案,能帮你避免 99% 的坑。
project-root/
├── public/ # Web 服务器根目录(DocumentRoot)
│ ├── index.php # 单一入口文件
│ ├── .htaccess # Apache URL 重写规则(可选)
│ ├── nginx.conf.example # Nginx 重写规则示例(可选)
│ └── static/ # 静态资源(CSS、JS、图片等)
├── config/ # 配置文件
│ ├── app.php # 应用配置
│ ├── database.php # 数据库配置
│ ├── cache.php # 缓存配置
│ └── routes.php # 路由定义(或放在单独目录)
├── app/ # 核心业务代码
│ ├── Controllers/ # 控制器
│ │ ├── Admin/
│ │ └── Api/
│ ├── Models/ # 数据模型 / 实体
│ ├── Services/ # 业务逻辑层(领域服务)
│ ├── Repositories/ # 数据仓库层(数据访问抽象)
│ ├── Middleware/ # 中间件(权限验证、日志等)
│ ├── Exceptions/ # 自定义异常类
│ ├── Helpers/ # 辅助函数(有时放在全局)
│ └── Providers/ # 服务提供者(框架/DI 容器相关)
├── database/ # 数据库相关
│ ├── migrations/ # 迁移文件
│ └── seeds/ # 填充数据
├── resources/ # 视图 / 语言 / 未编译资源
│ ├── views/ # 视图模板文件(blade、twig、phtml 等)
│ ├── lang/ # 语言包(多语言支持)
│ └── assets/ # 未编译的前端资源(SCSS、Vue 组件等)
├── storage/ # 运行时文件(日志、缓存、上传文件等)
│ ├── logs/ # 日志文件
│ ├── cache/ # 缓存文件
│ └── app/ # 用户上传文件等(需做权限处理)
├── tests/ # 单元测试 / 功能测试
│ ├── Unit/
│ └── Feature/
├── vendor/ # Composer 依赖管理(自动生成,不要手动修改)
├── .env # 环境变量(不应提交到 Git)
├── .env.example # 环境变量示例(应提交到 Git)
├── composer.json # Composer 配置
├── composer.lock # Composer 版本锁定文件
├── package.json # 前端依赖(如使用 npm/yarn)
└── artisan / console # 命令行入口(如 artisan 或自定义 CLI 文件)
优点:
- 安全性极高:
public目录是唯一对外暴露的,任何对app/、config/、storage/的直接 URL 访问都会被服务器拒绝。 - 结构清晰:每一层都有明确的职责,便于团队多人协作。
- 生态丰富:直接适配 Laravel、Symfony 等主流框架的思想,学习资料海量。
- 可测试性:天然支持单元测试和功能测试。
适用场景:
- 任何中大型项目。
- 任何使用现代框架(Laravel、Symfony、ThinkPHP 6/8+)的项目。
- 任何需要长期维护、团队协作的项目。
轻量级 / 微服务结构
如果项目较小且不使用重型框架,或者使用 Slim、Lumen 等微框架。
project-root/
├── public/
│ └── index.php # 入口文件
├── src/ # 所有业务代码
│ ├── Controllers/
│ │ └── HomeController.php
│ ├── Models/
│ │ └── User.php
│ ├── Middleware/
│ ├── Routing/
│ └── Support/ # 辅助工具类
├── config/
│ └── app.php
├── views/ # 视图模板
├── storage/
├── tests/
├── vendor/
├── composer.json
└── .env
不同点:
- 去掉了
app目录,直接用src。 - 去掉了过多的分层(如没有强制
Services和Repositories)。 - 视图文件直接放在根目录下(或
resources/views)。
适用场景:
- 小型 API 项目或简单 Web 应用。
- 使用 Slim、Lumen、Flight 等微框架。
模块化 / DDD 结构(高级)
对于大型复杂业务系统,推荐领域驱动设计(DDD)的模块化。
project-root/
├── public/
├── modules/ # 业务模块
│ ├── User/ # 用户模块
│ │ ├── Controllers/
│ │ ├── Models/
│ │ ├── Services/
│ │ ├── Repositories/
│ │ └── Tests/
│ ├── Order/ # 订单模块
│ │ └── ...
│ └── Payment/ # 支付模块
│ └── ...
├── core/ # 核心基础设施
│ ├── BaseController.php
│ ├── BaseModel.php
│ └── Exceptions/
├── config/
├── database/
├── resources/
├── storage/
├── vendor/
└── composer.json
优点:
- 高内聚,低耦合:每个模块独立,模块间通过接口或事件通信。
- 团队独立:不同团队可以独立开发不同模块,互不影响。
- 可拆分为微服务:当项目变大后,可以轻松将某个模块抽取为单独的微服务。
适用场景:
- 大型、复杂、长期的业务系统(如电商、ERP、CRM)。
- 团队规模较大(10人以上)。
- 计划未来进行微服务拆分。
一些细节建议
-
public目录的权限- 配置 Web 服务器(Nginx/Apache)的
document root直接指向public目录。 - 永远不要将
index.php之外的 PHP 文件放在public目录下(除非是非常特殊的静态生成文件)。
- 配置 Web 服务器(Nginx/Apache)的
-
vendor目录- 永远不要手动修改
vendor内的文件。 - 将
vendor加入.gitignore文件。 - 在部署时运行
composer install --no-dev。
- 永远不要手动修改
-
storage目录- 确保
storage目录在运行时对 Web 服务器用户有写权限(如chmod -R 775 storage)。 - 将其加入
.gitignore(除了storage/.gitkeep占位文件)。
- 确保
-
配置文件
- 使用
.env文件存储敏感信息(数据库密码、API Key 等)。 - 在
.gitignore中加入.env文件。 - 提交一个
.env.example作为模板。
- 使用
-
命名空间 (Namespace) 与自动加载
- 使用 PSR-4 自动加载标准(通过 Composer 配置)。
- 命名空间与目录结构保持严格一致。
app/Controllers/Api/UserController.php的命名空间为App\Controllers\Api\UserController。
-
视图位置
- 主流框架通常将视图放在
resources/views中。 - 如果使用模板引擎(如 Smarty、Twig),编译后的缓存文件建议放在
storage/cache中。
- 主流框架通常将视图放在
如何选择?
| 项目类型 | 推荐结构 |
|---|---|
| 个人项目 / 学习 | 方案二(轻量级)或 直接使用 Laravel/ThinkPHP 默认结构 |
| 小型团队 / 中小型项目 | 方案一(框架标准结构) |
| 大型团队 / 复杂业务 | 方案一 + 模块化(方案三) |
| 微服务 | 每个微服务独立使用方案一 |
| 老旧项目 / 无框架 | 逐步重构到方案一,至少做好 public/ 目录隔离 |
一句话建议:直接使用一个现代框架(Laravel 或 ThinkPHP),并严格遵循它的默认目录结构。 这样做不仅省心,而且能直接利用社区的最佳实践和工具生态,如果你需要自己搭建结构,请严格遵循方案一,那已经是经过无数项目验证的黄金标准。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播