Service Layer Pattern: Keeping Controllers Thin
Move business logic into services so controllers focus only on HTTP concerns.
As applications grow, controllers can become bloated. A service layer keeps code organized by separating responsibilities. Controller should focus on: - reading request - validation - returning response Service should focus on: - business rules - multi-step database updates - external API calls ## Example: OrderService ```php class OrderService { public function createOrder(User $user, array $items): Order { return DB::transaction(function () use ($user, $items) { $order = Order::create([ 'user_id' => $user->id, 'status' => 'pending', 'total' => 0, ]); $total = 0; foreach ($items as $it) { $order->items()->create([ 'product_id' => $it['product_id'], 'qty' => $it['qty'], 'price' => $it['price'], ]); $total += $it['qty'] * $it['price']; } $order->update(['total' => $total]); return $order; }); } } ``` Controller: ```php public function store(Request $request, OrderService $service) { $data = $request->validate([ 'items' => 'required|array|min:1', 'items.*.product_id' => 'required|integer', 'items.*.qty' => 'required|integer|min:1', 'items.*.price' => 'required|numeric|min:0', ]); $order = $service->createOrder($request->user(), $data['items']); return response()->json($order, 201); } ``` ## Graph: responsibility separation ```mermaid flowchart LR A[Controller] --> B[Service Layer] B --> C[Models/DB] B --> D[External APIs] ``` In the next tutorial, we will build custom exceptions and consistent API error responses.