Laravel DDD模式:是否应将Try-Catch移至控制器及事务处理方案
Laravel DDD模式下事务与异常处理的分层设计
现有代码实现
PostController
public function store(StorePostRequest $request): JsonResponse { return $this->postService->store($request); }
PostService
public function store(StorePostRequest $request): JsonResponse { DB::beginTransaction(); try { $post = new Post(); $post->uuid = Str::uuid(); $post->title = $request->input('title'); $post->description = $request->input('description'); $post->status_id = $request->input('status_id'); $post->created_by_user_id = Auth::id(); $this->postRepository->store($post); DB::commit(); return response()->json(['status' => true, __('service.the_operation_was_successful')]); } catch (Exception $exception) { DB::rollBack(); return response()->json(['status' => false, __('service.error_occurred_during_operation')], 500); } }
PostRepository
public function store(Post $post): Post { $post->save(); return $post; }
核心疑问
是否应该将try-catch块移至控制器端,以让Service层代码更简洁?如果迁移,该如何处理DB::beginTransaction()事务操作?
解答
1. 应该将异常处理移至控制器端
Service层的核心职责是处理业务逻辑,不应该耦合HTTP响应、异常返回这类Web请求相关逻辑。把try-catch移到控制器后:
- Service层代码更纯粹,可复用性更强(比如被CLI命令、队列任务调用时,无需适配HTTP响应逻辑);
- 符合分层设计原则:控制器专注处理HTTP请求与响应,Service专注业务规则,Repository专注数据持久化。
2. 事务操作的优化处理
无需手动管理beginTransaction()、commit()、rollBack(),可以利用Laravel提供的DB::transaction()闭包自动处理事务,同时让异常自然向上抛出给控制器处理。
重构后的代码示例
重构PostService
去掉HTTP响应和异常捕获,专注业务逻辑与事务管理:
public function store(StorePostRequest $request): Post { // 闭包自动管理事务:无异常自动提交,有异常自动回滚 return DB::transaction(function () use ($request) { $post = new Post(); $post->uuid = Str::uuid(); $post->title = $request->input('title'); $post->description = $request->input('description'); $post->status_id = $request->input('status_id'); $post->created_by_user_id = Auth::id(); return $this->postRepository->store($post); }); }
重构PostController
负责捕获异常并返回HTTP响应:
public function store(StorePostRequest $request): JsonResponse { try { $this->postService->store($request); return response()->json(['status' => true, __('service.the_operation_was_successful')]); } catch (Exception $exception) { return response()->json(['status' => false, __('service.error_occurred_during_operation')], 500); } }
进阶优化:自定义业务异常
如果需要区分业务逻辑错误和系统错误,可以自定义业务异常类(比如PostCreationFailedException),在Service层不符合业务规则时抛出,控制器针对性捕获处理:
// 自定义异常类 class PostCreationFailedException extends \Exception {} // Service层抛出异常 public function store(StorePostRequest $request): Post { return DB::transaction(function () use ($request) { // 新增业务校验逻辑 if (empty($request->input('title'))) { throw new PostCreationFailedException('标题不能为空'); } $post = new Post(); // ... 赋值逻辑 return $this->postRepository->store($post); }); } // 控制器捕获不同异常 public function store(StorePostRequest $request): JsonResponse { try { $this->postService->store($request); return response()->json(['status' => true, __('service.the_operation_was_successful')]); } catch (PostCreationFailedException $e) { return response()->json(['status' => false, $e->getMessage()], 400); } catch (Exception $e) { return response()->json(['status' => false, __('service.error_occurred_during_operation')], 500); } }
内容的提问来源于stack exchange,提问作者JFeel
相关产品推荐
相关产品推荐

