Атрибут MapRequestPayload
Атрибут MapRequestPayload вешается на аргумент метода
контроллера и автоматически преобразует данные тела
HTTP-запроса в объект указанного класса DTO. Атрибут
использует сериализатор Symfony для десериализации данных
из формата JSON, XML или form-data в свойства объекта.
Если валидация объекта не проходит, Symfony автоматически
возвращает ответ с ошибками валидации и статусом 422.
Синтаксис
#[MapRequestPayload(
acceptFormat: 'json',
resolver: null,
validationGroups: null,
serializationContext: [],
validationFailedStatusCode: 422
)]
Пример
Давайте создадим DTO-класс для приёма данных статьи:
<?php
namespace AppDto;
use SymfonyComponentValidatorConstraints as Assert;
class ArticleDto
{
#[AssertNotBlank]
public string $title = '';
#[AssertNotBlank]
public string $text = '';
#[AssertPositive]
public int $views = 0;
}
?>
Теперь используем атрибут MapRequestPayload
в методе контроллера для приёма JSON-запроса:
<?php
namespace AppController;
use AppDtoArticleDto;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyComponentHttpKernelAttributeMapRequestPayload;
use SymfonyComponentRoutingAttributeRoute;
class ArticleController extends AbstractController
{
#[Route('/article/create', name: 'article_create', methods: ['POST'])]
public function create(#[MapRequestPayload] ArticleDto $dto): JsonResponse
{
return new JsonResponse([
'title' => $dto->title,
'text' => $dto->text,
'views' => $dto->views,
]);
}
}
?>
Результат выполнения кода для JSON-запроса
{"title": "hello", "text": "article", "views": 5}:
{"title":"hello","text":"article","views":5}
Пример
Давайте ограничим допустимый формат запроса только JSON
с помощью параметра acceptFormat:
<?php
namespace AppController;
use AppDtoArticleDto;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyComponentHttpKernelAttributeMapRequestPayload;
use SymfonyComponentRoutingAttributeRoute;
class ArticleController extends AbstractController
{
#[Route('/article/update', name: 'article_update', methods: ['POST'])]
public function update(
#[MapRequestPayload(acceptFormat: 'json')] ArticleDto $dto
): JsonResponse {
return new JsonResponse(['title' => $dto->title]);
}
}
?>
Если клиент отправит запрос с заголовком
Content-Type отличным от application/json,
Symfony вернёт ответ со статусом 415.
Пример
Давайте укажем группу валидации через параметр
validationGroups:
<?php
namespace AppController;
use AppDtoArticleDto;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyComponentHttpKernelAttributeMapRequestPayload;
use SymfonyComponentRoutingAttributeRoute;
class ArticleController extends AbstractController
{
#[Route('/article/store', name: 'article_store', methods: ['POST'])]
public function store(
#[MapRequestPayload(validationGroups: ['strict'])] ArticleDto $dto
): JsonResponse {
return new JsonResponse(['text' => $dto->text]);
}
}
?>
При нарушении правил валидации Symfony вернёт ответ со статусом 422 и списком ошибок.
Смотрите также
-
атрибут
MapQueryString,
который преобразует query-параметры в объект DTO -
атрибут
MapQueryParameter,
который привязывает отдельный query-параметр к аргументу -
атрибут
MapUploadedFile,
который привязывает загруженный файл к аргументу -
атрибут
MapEntity,
который автоматически загружает сущность из базы данных