Laravel 项目开发规范 Service 模式
介绍
项目中的大部分业务逻辑,都应该封装到 Service 层。这不仅能更好地组织代码,还方便单元测试。
ModelService
Model 的操作,涉及到业务逻辑的,绝不放置于控制器方法或模型文件中。
控制器方法只处理请求逻辑。模型只处理模型定义,以及数据关联逻辑。
业务逻辑必须封装到对应的 ModelService 类中。
例如 LearnKu.com 的 Reply 模型,用户发布 Reply 时需要的逻辑,如发送通知给话题的作者,或者增加话题的评论数等操作,放置于 ReplyService 类的 create 方法。
ModelService 方法命名
必须参照 Laravel Model 的方法来命名,如:
$reply_service->create();
$reply_service->all();
$reply_service->update();
$reply_service->delete();
其他 Service
其他类型的类,都应该使用 Service 来封装,例如说:
请求第三方接口的类(SendCloudService)
图片处理的工具类(ImageService)
包含业务逻辑的类(对 Elasticsearch 封装的 SearchService )
存放目录
所有的 Service 类都必须存放于 app/Services
目录中(注意是复数)。
目录组织
应该避免直接将 Service 类放置于 app/Services
目录下,应该考虑通过业务逻辑,将其归类于子目录中。如:
Auth —— 存放登录、授权相关的 Service;
Payment —— 存放支付相关的 Service;
Book —— 存放课程相关的 Service.
Service 方法无状态
必须 做到 Service 类无状态。
无状态意味着是无论在控制器方法、命令行、测试代码中,皆可调用。
❌ 错误的例子:
// CommentService
public function create($content)
{
return Comment::create([
'content' => $content,
'user_id' => Auth::user()->id
]);
}
// PostService
public function update(Request $request)
{
return $this->comments()->create([
'content' => $request->get('content'),
'category_id' => $request->category_id
'user_id' => Auth::user()->id
]);
}
✅正确的例子
// CommentService
public function create($content, $user)
{
return Comment::create([
'content' => $content,
'user_id' => $user->id
]);
}
// PostService
public function create($content, $category_id, $user)
{
return Post::create([
'content' => $content,
'category_id' => $category_id,
'user_id' => $user->id
]);
}
更多建议: