说白了,如果TP5.1的Controller层直接跟Db::table()玩上了,验证逻辑到处乱塞,业务判断随手一写,那这控制器早就不是控制器了,而是个“缝合怪调度中心”。这样的代码,维护成本会随着迭代翻着跟头往上涨——不是“难维护”,是“根本不敢动”。

一旦在Controller里看到Db::table(),直接喊停就好
TP5.1的Db类确实是数据访问的快捷入口,但它不应该出现在Controller里。一旦看到类似这样的代码:
$user = Db::table('user')->where('id', $id)->find();
这就说明职责已经泄漏了:Controller揽下了数据获取、基础过滤、状态组装三件事。后续要加个字段映射、改个关联查询、补个缓存逻辑,都得改Controller,测试也得跟着重写。
- 正确的路径是:Controller → Service → Repository(或Model)
- Service层负责组合逻辑(比如“查用户 + 查其最近3条订单 + 拼装头像URL”),Repository负责单表CRUD
- TP5.1里可以建
app\common\repository\UserRepository,把Db::table('user')封装进它的findById()方法里 - Controller只保留
$this->userService->getProfile($id)这种语义清晰的调用
validate()确实是好工具,但千万别把它当成万能胶,随手往request()上一贴就完事
TP5.1的validate()很方便,但如果把它当成补丁,打在request()->param()后面,很快就会失控。常见的症状包括:
- 同一个字段在多个方法里重复定义规则(比如
'email' => 'require|email'出现在5个Controller方法里) - 规则里塞了业务逻辑(
'password' => 'require|checkOldPassword:uid',把密码校验耦合进验证器) - 验证失败后手动拼
['code'=>400, 'msg'=>'xxx'],和统一响应结构冲突
建议的做法是:
- 每个业务动作建独立的验证器类,比如
app\validate\User\UpdateProfileValidate - 验证器只做字段格式、长度、必填等基础检查;业务规则(比如“新邮箱不能与旧邮箱相同”)移入Service层
- 在基类
Controller中统一拦截ValidateException,转为Result::fail(400, $e->getMessage())
Service层别变成Controller的镜像副本
很多重构其实就是把Controller里的代码剪切粘贴到Service,方法名照抄(index()、save()、delete()),参数一模一样。这根本没解决问题——只是把“胖Controller”换成了“胖Service”。
真正有效的Service接口设计,应该满足这些条件:
- 方法名体现业务意图,而不是HTTP动词:
createUserWithInviteCode()比save()明确得多 - 参数尽量聚合:用
UserCreateDTO对象传参,而不是一堆$name, $email, $phone, $source - 返回值类型稳定:不返回
array或bool,统一用Result包装,即使成功也带data字段(空数组或null) - 事务边界清晰:一个Service方法对应一个完整业务用例,跨表操作必须包裹
Db::transaction()
View层里嵌PHP逻辑,是重构时最容易被忽略的腐化点
TP5.1的模板引擎支持{:function()}和{php}...{/php},但这类用法在重构时最容易成为盲区。比如:
{volist name="list" id="vo"}{:date('Y-m-d', $vo.create_time)}{if $vo.status == 1}已启用{else}已禁用{/if}{/volist}
这类逻辑本该由Controller或Service提前处理好。比如:
- 把
create_time格式化成字符串字段塞进$vo,模板只做展示 - 状态码转文字映射放到Service层(
statusText($vo.status)),Controller组装进data返回 - 模板里只留纯变量插值:
{$vo.formatted_create_time} {$vo.status_text}
否则,前端改个日期格式,或者运营要加个“试用期状态”标签,都得翻模板、找PHP片段、改逻辑、再测——这不是前端工作,是后端调试。
最难重构的,从来不是哪行代码写错了,而是那些“跑得通、看起来没问题、但谁都不敢删”的胶水逻辑。它们潜藏在验证器里、混在模板中、躺在Service方法命名背后。重构TP5.1项目,关键不是换框架,而是让每一层只说自己的语言:Controller说“我要什么”,Service说“这事怎么干”,Repository说“数据在哪”,View说“我怎么画”。