✍️ Вступ:
У Laravel зручно розміщувати бізнес-логіку у контролерах або моделях. Але що робити, коли логіка розростається? Вірне рішення — винести її в окремі сервіс-класи. Це дозволяє дотримуватись принципу SRP (Single Responsibility Principle) та робити код масштабованим і зручним для тестування.
🧱 Структура сервіс-класу
Розглянемо приклад сервісу для створення замовлення:
app/
├── Services/
│ └── OrderService.php
namespace App\Services; use App\Models\Order; use App\Models\User; use Illuminate\Support\Facades\DB; class OrderService { public function create(array $data, User $user): Order { return DB::transaction(function () use ($data, $user) { $order = new Order(); $order->user_id = $user->id; $order->total = $data['total']; $order->status = 'new'; $order->save(); // тут можна викликати події, надіслати email, тощо return $order; }); } }
🚀 Використання в контролері
namespace App\Http\Controllers; use App\Http\Requests\OrderRequest; use App\Services\OrderService; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Auth; class OrderController extends Controller { public function __construct( protected OrderService $orderService ) {} public function store(OrderRequest $request): JsonResponse { $order = $this->orderService->create($request->validated(), Auth::user()); return response()->json([ 'message' => 'Order created successfully.', 'order' => $order, ]); } }
✅ Переваги такого підходу:
- Чиста архітектура: контролери “худнуть” і стають точками входу, а не логічним смітником.
- Легкість тестування: можна мокати залежності та тестувати сервіси окремо.
- Гнучкість: сервіс легко розширити без змін у контролерах.
- Повторне використання: один сервіс можна викликати з різних частин системи (REST, CLI, Queue).
🧪 Як протестувати сервіс
use App\Models\User; use App\Services\OrderService; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class OrderServiceTest extends TestCase { use RefreshDatabase; public function test_it_creates_an_order() { $user = User::factory()->create(); $data = ['total' => 1000]; $service = new OrderService(); $order = $service->create($data, $user); $this->assertDatabaseHas('orders', [ 'user_id' => $user->id, 'total' => 1000, ]); } }
🔚 Висновок:
Сервіс-класи — це не "overengineering", а шлях до стійкої та чистої архітектури. Вони допомагають будувати Laravel-проєкти, які зручно підтримувати і масштабувати.