Ответ
Цель — вынести логику валидации и преобразования запроса в DTO из сервиса, оставив в контроллере только координацию. Вот как я это делаю в Symfony-проектах:
1. Использование форм для валидации DTO: Создаю форму, привязанную к DTO. Форма автоматически валидирует данные и заполняет объект DTO.
// src/Controller/UserController.php
use AppDtoUserUpdateDto;
use AppFormUserUpdateType;
use AppServiceUserService;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
class UserController extends AbstractController
{
public function update(
Request $request,
UserService $userService
): Response {
// 1. Создаём экземпляр DTO
$userUpdateDto = new UserUpdateDto();
// 2. Создаём и обрабатываем форму для этого DTO
$form = $this->createForm(UserUpdateType::class, $userUpdateDto);
$form->submit($request->toArray()); // Или handleRequest()
// 3. Валидация. Форма использует constraints из DTO.
if (!$form->isValid()) {
// Возвращаем ошибки валидации
return $this->json(['errors' => $form->getErrors(true)], Response::HTTP_BAD_REQUEST);
}
// 4. Передаём чистый, валидированный DTO в сервисный слой
$updatedUser = $userService->updateUser($userUpdateDto);
// 5. Сериализуем результат (например, через встроенный JsonResponse)
return $this->json($updatedUser, Response::HTTP_OK);
}
}
2. Использование сериализатора и валидатора (для API без форм):
// Альтернативный подход с @ParamConverter или ручной десериализацией
public function update(
Request $request,
SerializerInterface $serializer,
ValidatorInterface $validator,
UserService $userService
): Response {
// Десериализуем JSON-тело запроса сразу в DTO
$userUpdateDto = $serializer->deserialize(
$request->getContent(),
UserUpdateDto::class,
'json'
);
// Валидируем DTO
$errors = $validator->validate($userUpdateDto);
if (count($errors) > 0) {
// Обработка ошибок...
}
// Передаём в сервис
$userService->updateUser($userUpdateDto);
return $this->json(['status' => 'success']);
}
Ключевой принцип: Контроллер отвечает за HTTP-взаимодействие (десериализацию, валидацию входных данных, формирование ответа). Сервис получает уже готовый к использованию, гарантированно валидный объект DTO и работает только с бизнес-логикой.