PHP项目怎样划分业务目录模块

wen PHP项目 29

本文目录导读:

PHP项目怎样划分业务目录模块

  1. 方案一:基于领域/业务模块划分(推荐,适用于MVC框架)
  2. 方案二:DDD(领域驱动设计)分层(适用于大型复杂项目)
  3. 方案三:按功能层级划分(传统的扁平结构,适合小型项目)
  4. 方案四:微服务拆分(独立项目 + 共用基建)
  5. 实际操作中的最佳实践建议
  6. 快速启动模板(基于 Laravel 风格的模块化推荐)

在PHP项目中划分业务目录模块,核心原则是按业务领域(Domain)拆分,而不是按技术类型(Controller、Model、View)来写,这样能确保高内聚、低耦合,方便多人协作和后期维护。

以下是当前PHP主流项目(如基于Laravel、ThinkPHP、Symfony或自研框架)推荐的几种目录划分方案,从简单到复杂,供你参考:


基于领域/业务模块划分(推荐,适用于MVC框架)

这是目前最主流、最适合中大型项目的做法,核心思想是:一个业务模块就是一个小型完整应用

project/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Admin/            # 后台管理
│   │   │   │   ├── UserController.php
│   │   │   │   └── OrderController.php
│   │   │   └── Api/              # API接口
│   │   │       ├── V1/           # 版本控制
│   │   │       └── V2/
│   │   └── Middleware/
│   │
│   ├── Models/                    # 数据库模型(可保留,但更推荐放领域)
│   │
│   ├── Modules/                   # 【核心】按业务模块划分
│   │   ├── User/                  # 用户模块
│   │   │   ├── Controllers/       # 模块内部的控制器
│   │   │   ├── Models/            # 模块内部的模型
│   │   │   ├── Services/          # 模块业务逻辑层
│   │   │   ├── Repositories/      # 数据仓储层(可选)
│   │   │   ├── Requests/          # 表单验证
│   │   │   ├── Resources/         # API资源转换
│   │   │   └── Tests/             # 单元测试
│   │   │
│   │   ├── Order/                 # 订单模块
│   │   │   ├── Controllers/
│   │   │   ├── Models/
│   │   │   ├── Services/
│   │   │   └── ...
│   │   │
│   │   └── Payment/               # 支付模块
│   │       └── ...
│   │
│   └── Exceptions/                # 异常处理
│
├── config/    
├── database/
│   ├── migrations/                # 数据库迁移(可按模块分文件)
│   └── seeds/
├── routes/                        # 路由文件
│   ├── web.php                    # 前端页面路由
│   ├── api.php                    # API路由
│   └── admin.php                  # 后台路由
├── resources/                     # 视图文件
│   └── views/
│       ├── admin/
│       └── modules/               # 按模块存放视图
└── tests/

优点

  • 业务内聚性强,修改一个模块功能时,不会影响其他模块。
  • 新成员入职只需要关注自己负责的模块目录。
  • 未来可以很容易把某个模块拆成独立微服务。

适用场景:ERP、电商、OA、SaaS等业务逻辑复杂的系统。


DDD(领域驱动设计)分层(适用于大型复杂项目)

如果你的项目业务极度复杂(如金融、医疗、工业软件),推荐引入领域层,结构会更清晰。

project/
├── app/
│   ├── Application/                # 应用层(调度、DTO、用例)
│   │   └── UseCases/
│   │       ├── CreateOrderUseCase.php
│   │       └── UserRegisterUseCase.php
│   │
│   ├── Domain/                     # 领域层(核心业务规则)
│   │   ├── User/
│   │   │   ├── User.php           # 实体
│   │   │   ├── UserRepository.php # 仓储接口
│   │   │   └── UniqueEmailSpec.php# 业务规约
│   │   └── Order/
│   │       └── ...
│   │
│   ├── Infrastructure/            # 基础设施层(数据库、队列、第三方)
│   │   ├── Repositories/
│   │   │   └── UserRepositoryEloquent.php
│   │   └── Services/
│   │       └── PaymentGateway.php
│   │
│   ├── Interfaces/                # 接口层(HTTP、CLI等)
│   │   ├── Controllers/
│   │   ├── Requests/
│   │   └── Resources/
│   │
│   └── Shared/                    # 公共工具、值对象
│       └── ValueObject/
│           └── Money.php
│
└── routes/

优点

  • 严格遵守单一职责,业务逻辑与框架解耦。
  • 适合需要长期迭代、业务模型稳定的项目。

缺点

  • 初期搭建成本高,不太适合简单项目。

按功能层级划分(传统的扁平结构,适合小型项目)

对于CRUD为主的简单项目(如博客、公司官网),可以简单按技术职责划分。

project/
├── app/
│   ├── Controller/
│   │   ├── HomeController.php
│   │   ├── PostController.php
│   │   └── UserController.php
│   ├── Model/
│   │   ├── Post.php
│   │   └── User.php
│   ├── Service/
│   │   ├── PostService.php
│   │   └── UserService.php
│   └── Helper/
├── config/
├── view/
└── route/

优点:简单直接,上手快。

缺点:随着项目复杂度增加,一个 Controller 会膨胀到几千行,难以维护。不建议用于中型以上项目


微服务拆分(独立项目 + 共用基建)

如果项目规模很大,团队人员多,可以按业务拆分为独立的微服务项目。

project-root/
├── services/
│   ├── user-service/               # 用户微服务(独立项目)
│   │   ├── app/
│   │   ├── config/
│   │   ├── database/
│   │   └── composer.json
│   │
│   ├── order-service/              # 订单微服务
│   │   └── ...
│   │
│   └── payment-service/            # 支付微服务
│       └── ...
│
└── shared/                         # 共用库(通过Composer包引入)
    ├── contracts/                  # 接口契约
    └── common/                     # 公共工具类

优点:独立部署、独立开发。

缺点:分布式中的事务、通信、运维复杂度高。


实际操作中的最佳实践建议

无论你采用哪种方案,以下几个原则能让你的目录更清晰:

每个模块内尽量自闭环

不要跨模块直接调用另一个模块的Model,应通过 Service 层接口(Interface) 进行交互,订单模块需要用户信息,应通过 UserService::getUserInfo() 而不是 User::find()

区分“通用模块”与“业务模块”

Modules/
├── Common/                     # 通用模块(工具类、文件上传、短信、日志)
├── Admin/                      # 管理后台(权限、菜单、角色)
├── User/                       # 用户模块
├── Order/                      # 订单模块
└── Payment/                    # 支付模块
  • Common 模块没有业务耦合,所有模块都可以依赖它。
  • 其他业务模块之间尽量不要有相互依赖,如果需要,通过 Event/ListenerService 接口 解耦。

命名空间规范化

composer.json 中配置 PSR-4 自动加载,让命名空间与目录结构一一对应。

{
  "autoload": {
    "psr-4": {
      "App\\Modules\\User\\": "app/Modules/User/",
      "App\\Modules\\Order\\": "app/Modules/Order/"
    }
  }
}

这样在代码中就可以写:

use App\Modules\User\Services\UserService;

根据项目规模选择合适的方案

项目类型 推荐方案 示例目录结构
个人博客、展示型网站 方案三(功能层级) Controller + Model + View
电商(3-5人团队) 方案一(业务模块) Modules/User,Modules/Order
金融 / 大型SaaS(6人+) 方案二(DDD) Domain / Application / Infrastructure
多团队并行开发 方案四(微服务) services/user-service

快速启动模板(基于 Laravel 风格的模块化推荐)

如果你现在开始一个中间大小的项目,这个结构比较稳妥:

app/
├── Modules/
│   ├── Shopping/
│   │   ├── Controllers/
│   │   ├── Services/
│   │   ├── Models/
│   │   └── Providers/
│   ├── User/
│   │   └── ...
│   └── Admin/
│       └── ...
├── Providers/
├── Support/               # 服务提供者、门面、全局助手
└── Traits/

最后提醒一个常见的错误:不要把所有的 Model 都放在同一个 Models/ 目录下,那会导致模块边界模糊,时间长了谁也分不清哪些 Model 属于哪个功能。

抱歉,评论功能暂时关闭!