在现代 Web 开发中,项目的可维护性、可扩展性和团队协作效率是至关重要的。ThinkPHP8 提供了强大的多应用支持,通过合理的目录结构和开发规范,可以显著提升项目的整体质量。本文将详细介绍一个“能直接落地”的 ThinkPHP8 多应用目录结构模板,并逐层说明控制器、模型、服务层等各层的职责、命名规范和开发流程,帮助团队一次性对齐开发规范。
一、项目目录结构模板
以下是一个典型的 ThinkPHP8 多应用项目目录结构,以新建两个应用 index
和 admin
为例:
├─ app // 应用总目录
│ ├─ index // 【前台】应用
│ │ ├─ controller // 控制器层:只负责「接收请求、调度、返回」
│ │ │ ├─ Index.php // 默认首页控制器(类名:Index,文件名Index.php)
│ │ │ ├─ user // 多级控制器(URL:/user/profile)
│ │ │ │ └─ Profile.php // 类名:User\Profile(注意命名空间)
│ │ ├─ model // 数据层:一张表一个文件,只做「最原子」的 CURD
│ │ │ ├─ User.php // 类名:app\index\model\User,对应表前缀+user表
│ │ │ └─ Order.php
│ │ ├─ logic // 逻辑层(可选):拼装复杂查询、事务、业务规则
│ │ │ └─ UserLogic.php // 类名:app\index\logic\UserLogic
│ │ ├─ service // 服务层(可选):跨应用/跨模块可复用的“纯业务”
│ │ │ └─ PayService.php // 类名:app\index\service\PayService
│ │ ├─ validate // 验证器:一一对应控制器方法
│ │ │ └─ UserValidate.php
│ │ ├─ middleware // 应用级中间件
│ │ ├─ event.php // 事件监听定义
│ │ ├─ route // 应用路由,仅对本应用生效
│ │ │ └─ app.php
│ │ └─ view // 视图(若前后端不分离)
│ │ └─ index\index.html
│ │
│ ├─ admin // 【后台】应用,目录层级与 index 完全一致
│ │ ├─ controller
│ │ ├─ model
│ │ ├─ logic
│ │ ├─ service
│ │ ├─ validate
│ │ ├─ middleware
│ │ ├─ route
│ │ └─ view
│ │
│ └─ common // 多应用共享代码
│ ├─ model // 公共模型(如AdminBase、CommonLogic)
│ ├─ service // 全局服务(SmsService、FileService…)
│ ├─ middleware // 全局中间件(Auth、Log、Cors…)
│ ├─ bootstrap.php // 应用启动时统一加载
│ └─ event.php // 全局事件
│
├─ config // 全局配置
│ ├─ app.php // 开启 auto_multi_app => true
│ ├─ database.php
│ └─ …
├─ public // Web 根
│ ├─ index.php // 单入口
│ └─ static // 静态资源
├─ runtime // 缓存、日志、文件缓存
└─ extend / vendor // 本地扩展 & Composer 包
二、各层职责与命名规范
- 控制器(controller)
职责:只负责接收请求、调用业务逻辑、渲染视图或返回 JSON 数据。禁止出现 SQL 或业务规则。
命名规范:
- 类名与文件名一致,采用驼峰命名法。例如:
Index.php
→ 类名Index
。 - 多级控制器再加一层子目录,例如
user/Profile.php
→ 类名User\Profile
。 - 强制使用
validate
或Validate
类完成入参校验,控制器里不出现$_POST
直接取值。
示例:
namespace app\index\controller;
use app\index\logic\UserLogic;
use think\facade\Request;
use think\facade\View;
class Index
{
public function index()
{
$data = Request::param();
$result = UserLogic::getUserInfo($data);
return View::fetch('index/index', ['data' => $result]);
}
}
- 模型(model)
职责:一张主表对应一个 Model 文件,只封装“最原子”的 CURD、自动时间戳、软删、关联模型。所有对表字段的默认值、枚举转换、获取器/修改器,写在 Model;不出现复杂联表。
命名规范:
- 表名转驼峰,例如
user_cards
→UserCards.php
。 - 类名与文件名一致,采用驼峰命名法。
示例:
namespace app\index\model;
use think\Model;
class User extends Model
{
protected $name = 'user'; // 数据表名
protected $autoWriteTimestamp = true; // 自动时间戳
protected $deleteTime = 'delete_time'; // 软删除字段
public function orders()
{
return $this->hasMany(Order::class);
}
}
- 逻辑层(logic)
职责:当“一个业务需要操作多张表 or 需要事务 or 需要缓存/加锁”时,在 Logic 里拼装。一个 Logic 类通常对应一个“业务域”,如 OrderLogic::createOrder()
。
命名规范:
- 类名与文件名一致,采用驼峰命名法。例如:
UserLogic.php
→ 类名UserLogic
。
示例:
namespace app\index\logic;
use app\index\model\User;
use think\Exception;
class UserLogic
{
public static function getUserInfo($data)
{
try {
$user = User::where('id', $data['id'])->find();
if (!$user) {
throw new Exception('User not found');
}
return $user->toArray();
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
}
- 服务层(service)
职责:与具体应用无关、可跨应用/跨项目复用的“纯业务”才下沉到 Service,如 SmsService
、FileService
。Service 里禁止直接 use think\facade\Db
,只能调用 Model/Logic 提供的接口,保持可单元测试。
命名规范:
- 类名与文件名一致,采用驼峰命名法。例如:
PayService.php
→ 类名PayService
。
示例:
namespace app\index\service;
use app\index\logic\UserLogic;
class PayService
{
public function processPayment($data)
{
$userInfo = UserLogic::getUserInfo($data);
// 处理支付逻辑
return true;
}
}
- 公共层(common)
职责:多应用都要用的代码统一放在 app/common
;若以后拆微服务,可直接把 common 打成 Composer 包。common 里也可以再细分 model/service/middleware
子目录,命名空间统一 app\common\xxx
。
示例:
namespace app\common\model;
use think\Model;
class CommonModel extends Model
{
// 公共模型方法
}
三、快速生成命令(TP8 内置)
ThinkPHP8 提供了强大的命令行工具,可以快速生成应用骨架和多层文件,提高开发效率。
# 生成应用骨架
php think build demo
# 生成多层文件
php think make:controller demo@user/Member # 多级控制器
php think make:model demo@User # 模型
php think make:logic demo@UserLogic # 需安装 topthink/think-logic 或手写
php think make:validate demo@UserValidate # 验证器
四、开发流程小结
- 需求评审:明确需求,确定功能模块。
- 建表:根据需求设计数据库表结构。
- 先写 Model:封装表结构、字段、关联、获取器等。
- 再写 Logic/Service:实现业务逻辑,确保代码复用性和可测试性。
- 最后写 Controller:接收参数、调用业务逻辑、返回响应。控制器代码保持简洁,通常不超过 10 行。
遵循“控制器永远‘薄’,模型永远‘原子’,业务永远‘下沉’,跨应用代码永远进 common
”的原则,可以确保项目的长期可维护性、可扩展性和团队协作效率。
五、总结
通过合理的目录结构和开发规范,ThinkPHP8 多应用项目可以实现高效开发、易于维护和扩展。希望本文介绍的目录结构模板和开发规范能够帮助团队快速对齐,提升项目的整体质量。