check24/apitk-dtomapper-bundle

此包提供映射辅助工具,将REST动作映射到DTO并将它们序列化。

安装数: 3,205

依赖项: 0

建议者: 0

安全: 0

星标: 2

关注者: 1

分支: 6

类型:symfony-bundle

4.1.0 2022-01-06 13:22 UTC

README

概述

此包为RESTful API添加了版本化的DTO支持。

安装

使用composer安装此包

composer require check24/apitk-dtomapper-bundle

用法

设置

将以下内容添加到您的services.yaml中,以便包可以自动加载和使用映射服务

services:
    App\DtoMapper\:
        resource: '../src/DtoMapper'
        public: true

编写映射器

src/DtoMapper文件夹(或您配置的任何文件夹)中创建一个映射器类,该类实现MapperInterface并将传入的数据转换为单个DTO

use Shopping\ApiTKDtoMapperBundle\DtoMapper\MapperInterface;

class UserV1Mapper implements MapperInterface
{
    /**
     * @param User $data
     * @return Dto\UserV1
     */
    public function map($data): Dto\UserV1
    {
        $userDto = new Dto\UserV1();
        $userDto->setId($data->getId())
            ->setUsername($data->getUsername())
            ->setEmail($data->getEmail());

        return $userDto;
    }
}

在您的控制器中,将@Rest\View()注解替换为相应的@Dto\View(),并指明要使用的映射器

use FOS\RestBundle\Controller\Annotations as Rest;
use Shopping\ApiTKDtoMapperBundle\Annotation as DtoMapper;

/**
 * @Rest\Get("/v1/users")
 * @DtoMapper\View(dtoMapper="App\DtoMapper\UserV1Mapper")
 *
 * @param EntityManagerInterface $entityManager
 * @return User[]
 */
public function getUsersV1(EntityManagerInterface $entityManager)
{
    $userRepository = $entityManager->getRepository(User::class);

    $users = $userRepository->findAll();

    return $users;
}

现在,该包会自动将您在动作中返回的任何内容转换为DTO,使用给定的映射器。当您在控制器中返回数据数组时,映射器将对数组中的每个元素进行调用。您无需担心这一点。

如果您想跳过数组中的某些元素,可以抛出UnmappableException

此外,该包自动生成带有代码200和相应的DTO模式的swagger响应(分别是一个DTO数组),因此您无需添加冗余的@SWG\Response()。为此,只需确保您的映射器有一个正确的返回类型提示(例如public function map($data): FoobarDto),并且您的控制器动作有一个返回注解,该注解声明返回的是数组还是对象(例如* @return Foobar[])。您仍然可以通过自己的@SWG\Response()注解来覆盖此设置。

将数组转换为集合

如果您在控制器中返回数组,它将按此方式序列化。如果您不想使用数组或由于技术限制(例如protobuf)无法使用数组,您可以指示该包将数组转换为集合类。

要将控制器返回的数组转换为集合,请将MapperCollectionInterfaceMapperInterface一起实现到您的映射器中。

示例

use Shopping\ApiTKDtoMapperBundle\DtoMapper\MapperCollectionInterface;
use Shopping\ApiTKDtoMapperBundle\DtoMapper\MapperInterface;

class UserV1Mapper implements MapperInterface, MapperCollectionInterface
{
    /**
     * @param Dto\UserV1[] $items
     */
    public function mapCollection(array $items): Dto\UserV1Collection {
        $collection = new UserV1Collection();
        $collection->setItems($items);

        return $collection;
    }

    /**
     * @param Dto\UserV1 $data
     */
    public function map($data): Dto\UserV1
    {
        $userDto = new Dto\UserV1();
        $userDto->setId($data->getId())
            ->setUsername($data->getUsername())
            ->setEmail($data->getEmail());

        return $userDto;
    }
}

这将在通过map映射所有项目后调用mapCollection。您可以在mapCollection方法中初始化您的集合类。这里返回的对象将替换控制器响应的内容。

序列化DTO视图

如果您希望以serialize($dto)的方式返回DTO而不是JSON,请实现可用的DTO视图处理程序。

//fos_rest.yaml
fos_rest:
    view:
        mime_types:
            dto: ['application/vnd.dto'] # You can specify whatever mime type you want, just map it to "dto".
    service:
        view_handler: app.view_handler
    exception:
        serializer_error_renderer: true
//services.yaml
services:
    app.view_handler:
        autowire: true
        autoconfigure: false
        public: false
        parent: fos_rest.view_handler.default
        calls:
            - ['registerHandler', ['dto', ['@Shopping\ApiTKDtoMapperBundle\Handler\PhpViewHandler', 'createResponse']]]

当使用Accept: application/vnd.dto头调用API时,您将获得一个不可序列化的DTO字符串。

异常也会被序列化。当kernel.debug设置为false(=在生产环境中)时,会省略堆栈跟踪、文件名、行号和前面的异常,以避免泄露可能敏感的信息。

序列化Protobuf视图

如果您希望返回序列化的Protobuf对象。

//fos_rest.yaml
fos_rest:
    view:
        mime_types:
            proto: ['application/x-protobuf'] # You can specify whatever mime type you want, just map it to "proto".
    service:
        view_handler: app.view_handler
    exception:
        serializer_error_renderer: true
//services.yaml
services:
    app.view_handler:
        autowire: true
        autoconfigure: false
        public: false
        parent: fos_rest.view_handler.default
        calls:
            - ['registerHandler', ['proto', ['@Shopping\ApiTKDtoMapperBundle\Handler\ProtobufViewHandler', 'createResponse']]]