mops1k/ request-object-resolver-bundle
用于解析和验证HTTP请求到对象的包
v2.0.0
2023-12-11 07:32 UTC
Requires
- php: >=8.1
- doctrine/inflector: ^2.0
- symfony/framework-bundle: ^6.0
- symfony/property-access: ^6.0
- symfony/serializer: ^6.0
- symfony/validator: ^6.0
Requires (Dev)
- doctrine/annotations: ^1.14
- phpstan/phpstan: ^1.10
- phpstan/phpstan-phpunit: ^1.3
- phpstan/phpstan-strict-rules: ^1.5
- phpunit/php-code-coverage: ^10.1
- phpunit/phpunit: ^10.5
- roave/security-advisories: dev-latest
- symplify/config-transformer: ^12.0
- symplify/easy-coding-standard: ^11.5
README
此包可以帮助您将symfomy HTTP请求对象中的传入请求参数反序列化为您的DTO对象。
反序列化对象将通过symfony/validator进行验证,因此在使用控制器中的此类对象时,我们可以确保数据格式和对象中设置的格式正确,并且已准备好进一步处理。
包可以反序列化
- 路由参数(属性
RequestObjectResolverBundle\Attribute\Path
) - 查询参数(属性
RequestObjectResolverBundle\Attribute\Query
) - 内容主体(支持所有symfony序列化格式)(属性
RequestObjectResolverBundle\Attribute\Content
) - 表单参数(属性
RequestObjectResolverBundle\Attribute\Form
) - 上传文件(属性
RequestObjectResolverBundle\Attribute\Form
)
安装
composer require mops1k/request-object-resolver-bundle
使用
示例
<?php use RequestObjectResolverBundle\Attribute\Query; use RequestObjectResolverBundle\Attribute\Path; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\Constraints as Assert; class ExampleRequest { #[Assert\NotNull] #[Assert\GreaterThan(0)] public ?int $id = null; #[Assert\NotNull] #[Assert\NotBlank] public ?string $name = null; } /** * Request path example: /25?name=Julian */ class ExampleController extends AbstractController { #[Route('/{id}', methods: [Request::METHOD_GET])] public function __invoke(#[Query, Path] ExampleRequest $exampleRequest): JsonResponse { // some logic with $exampleRequest return new JsonResponse([ 'id' => $exampleRequest->id, 'name' => $exampleRequest->name, ]); } }
映射字段到另一个名称
整个库的属性都有一个映射参数。使用此参数,您可以从一个字段名映射到另一个字段名。
示例
<?php use RequestObjectResolverBundle\Attribute\Query; use RequestObjectResolverBundle\Attribute\Path; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\Constraints as Assert; class ExampleRequest { #[Assert\NotNull] #[Assert\GreaterThan(0)] public ?int $id = null; #[Assert\NotNull] #[Assert\NotBlank] public ?string $title = null; } /** * Request path example: /25?name=Julian */ class ExampleController extends AbstractController { #[Route('/{id}', methods: [Request::METHOD_GET])] public function __invoke(#[Query(map: ['name' => 'title']), Path] ExampleRequest $exampleRequest): JsonResponse { // some logic with $exampleRequest return new JsonResponse([ 'id' => $exampleRequest->id, 'title' => $exampleRequest->name, ]); } }
跳过DTO验证
如果您的逻辑由于某些原因不需要自动验证请求对象,则可以使用RequestObjectResolverBundle\Attribute\SkipValidation
属性禁用它。
示例
<?php use RequestObjectResolverBundle\Attribute\Query; use RequestObjectResolverBundle\Attribute\Path; use RequestObjectResolverBundle\Attribute\SkipValidation; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\Constraints as Assert; class ExampleRequest { #[Assert\NotNull] #[Assert\GreaterThan(0)] public ?int $id = null; #[Assert\NotNull] #[Assert\NotBlank] public ?string $name = null; } /** * Request path example: /-1?name= */ class ExampleController extends AbstractController { #[Route('/{id}', methods: [Request::METHOD_GET])] public function __invoke(#[Query, Path, SkipValidation] ExampleRequest $exampleRequest): JsonResponse { // some logic with $exampleRequest return new JsonResponse([ 'id' => $exampleRequest->id, 'name' => $exampleRequest->name, ]); } }
验证组
如果您想使用验证组,则请使用属性 \RequestObjectResolverBundle\Attribute\ValidationGroups
。
示例
<?php use RequestObjectResolverBundle\Attribute\Query; use RequestObjectResolverBundle\Attribute\Path; use RequestObjectResolverBundle\Attribute\ValidationGroups; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\Constraints as Assert; class ExampleRequest { #[Assert\NotNull] #[Assert\GreaterThan(0, groups: ['default'])] public ?int $id = null; #[Assert\NotNull] #[Assert\NotBlank] public ?string $name = null; } /** * Request path example: /25?name=Julian */ class ExampleController extends AbstractController { #[Route('/{id}', methods: [Request::METHOD_POST])] public function __invoke(#[Query, Path, ValidationGroups(groups: 'default')] ExampleRequest $exampleRequest): JsonResponse { // some logic with $exampleRequest return new JsonResponse([ 'id' => $exampleRequest->id, 'name' => $exampleRequest->name, ]); } }
序列化上下文
如果您想添加一些序列化上下文,则可以在属性中设置serializationContext
属性。
示例
<?php use RequestObjectResolverBundle\Attribute\Query; use RequestObjectResolverBundle\Attribute\Path; use RequestObjectResolverBundle\Attribute\ValidationGroups; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; class ExampleRequest { #[Assert\NotNull] #[Assert\GreaterThan(0)] #[Groups(['default'])] public ?int $id = null; #[Assert\NotNull] #[Assert\NotBlank] public ?string $name = null; } /** * Request path example: /25?name=Julian */ class ExampleController extends AbstractController { #[Route('/{id}', methods: [Request::METHOD_POST])] public function __invoke(#[Query(serializerContext: ['groups': ['default']]), Path] ExampleRequest $exampleRequest): JsonResponse { // some logic with $exampleRequest return new JsonResponse([ 'id' => $exampleRequest->id, 'name' => $exampleRequest->name, // will throw error as uninitialized property ]); } }
如果您想将上下文设置为所有要反序列化到对象的请求部分,请使用\RequestObjectResolverBundle\Attribute\SerializerContext
属性。
<?php use RequestObjectResolverBundle\Attribute\Query; use RequestObjectResolverBundle\Attribute\Path; use RequestObjectResolverBundle\Attribute\SerializerContext; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; class ExampleRequest { #[Assert\NotNull] #[Assert\GreaterThan(0)] #[Groups(['default'])] public ?int $id = null; #[Assert\NotNull] #[Assert\NotBlank] public ?string $name = null; } /** * Request path example: /25?name=Julian */ class ExampleController extends AbstractController { #[Route('/{id}', methods: [Request::METHOD_POST])] public function __invoke(#[Query, Path, SerializerContext(['groups': ['default']])] ExampleRequest $exampleRequest): JsonResponse { // some logic with $exampleRequest return new JsonResponse([ 'id' => $exampleRequest->id, 'name' => $exampleRequest->name, // will throw error as uninitialized property ]); } }
使用请求部分组合覆盖值
这是请求部分优先级覆盖表(如果具有相同的键名)
示例。如果您在同一对象中处理Path
、Query
和Content
,并且所有它们都有相同的字段(例如id),则最终字段的值将来自Form
请求部分。