Ответ
В Laravel я строго следую принципу "тонких контроллеров" и выношу логику в специализированные классы. Вот основные места и примеры из моего опыта:
1. Сервисные классы (Service Classes) — для бизнес-логики.
Размещаю в app/Services/. Контроллер делегирует им основную работу.
Пример: Сервис для регистрации пользователя.
// app/Services/UserRegistrationService.php
namespace AppServices;
use AppModelsUser;
use AppNotificationsWelcomeNotification;
class UserRegistrationService
{
public function register(array $data): User
{
// Вся бизнес-логика создания пользователя
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
// Отправка welcome-email через очередь
$user->notify(new WelcomeNotification());
// Логирование события
Log::info('New user registered', ['user_id' => $user->id]);
return $user;
}
}
// В контроллере
public function store(RegisterRequest $request, UserRegistrationService $service)
{
$user = $service->register($request->validated());
return response()->json($user, 201);
}
2. Action-классы или Jobs — для отдельных операций. Идеально для инкапсуляции сложной логики, которую можно повторно использовать.
php artisan make:action/CreateNewOrderAction
3. Form Request Validation — для валидации.
Выношу правила валидации из контроллера в отдельные классы app/Http/Requests/.
4. Репозитории — для абстракции работы с данными. Использую, когда нужен сложный доступ к данным или замена источника (БД, API, кэш).
// app/Repositories/UserRepository.php
class UserRepository
{
public function findActiveWithLatestOrder(int $userId): ?User
{
return User::where('id', $userId)
->where('is_active', true)
->with(['latestOrder'])
->first();
}
}
5. Events & Listeners — для реактивной логики.
Например, при создании заказа (OrderCreated) запускаются слушатели на отправку чека, обновление инвентаря и нотификацию менеджера.
Итог: Мой контроллер становится маршрутизатором (router), который:
- Валидирует входящий запрос (через Form Request).
- Вызывает нужный сервис, action или job.
- Возвращает HTTP-ответ. Это делает код контроллеров предсказуемым, тестируемым и легким для поддержки.