thinkphp6.1.5接口开发中应使用app/service下的pascalcase命名service类(如userloginservice)解耦业务,控制器仅收参、调服务、返json;service专注单一职责,依赖注入、参数封装、事务外移;配套中间件鉴权、接口抽象、事件驱动与通用服务复用。

ThinkPHP6.1.5 接口开发中用服务层解耦业务,核心是把控制器“减负”,让业务逻辑有归属、可测试、易替换。控制器只管收参、调服务、返回 JSON,其余全交给 app/service 下的 Service 类处理。
Service 层该放哪、怎么命名
目录必须是 app/service,与 app/controller 平级,不能塞进 app/common 或 app/logic。类名用 PascalCase,比如 UserLoginService、OrderCreateService,避免和模型(如 UserModel)或控制器(如 UserController)重名。命名要体现职责,不叫 UserService 这种泛称,而应聚焦场景,如 UserRegistrationService。
控制器只做三件事
一个接口方法里只保留以下动作:
- 接收请求参数(
$this->request->param()或验证后数据) - 通过容器获取服务实例:
app()->make(UserLoginService::class) - 调用服务方法并返回标准化响应:
return json($service->login($data))
不写数据库操作、不拼 SQL、不发 HTTP 请求、不手动控制事务、不处理权限判断——这些都移出去。
Service 类设计要点
每个 Service 类专注一个业务域,方法保持单一职责:
- 构造函数声明依赖,例如
public function __construct(private AuthInterface $auth, private SmsClient $sms),不要在方法里app()->make() - 方法参数用数组或 DTO 封装,比如
login(array $input),而不是login($username, $password, $captcha, $device_id) - 不调用
config()、env()或Db::,配置项由控制器传入,数据库操作交给 Model 或 Query 类 - 事务控制上提到控制器或命令行层,Service 内部不做
Db::transaction()
配合接口解耦的其他支撑点
光有 Service 不够,还得配套几处关键调整:
- 权限校验抽成中间件或独立 AuthService,控制器不再写
if (!$user || $user->role !== 'admin') - 第三方调用(短信、支付、估值)定义接口(如
SmsInterface),不同环境绑定不同实现(测试用 MockSms,生产用 AliyunSms) - 耗时操作(如发通知、记日志、更新积分)改用事件机制:
event(new UserLoggedIn($user)),监听器各自处理,主流程不阻塞 - 需要复用的通用能力(如分页、导出、文件上传)封装为独立服务,而非在多个 Service 里重复写
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











