crtl/request-dto-resolver-bundle

将请求反序列化并验证为对象

安装: 0

依赖: 0

建议者: 0

安全: 0

星星: 0

关注者: 1

分支: 0

开放问题: 0

类型:symfony-bundle

0.0.3 2024-06-04 22:33 UTC

This package is auto-updated.

Last update: 2024-09-05 23:50:29 UTC


README

Coverage Badge

用于简化请求 DTO 实例化和验证的 Symfony 扩展包。

功能

  1. 自动 DTO 处理:
    Request 数据中立即创建并验证与控制器动作中类型提示的数据传输对象 (DTO),从而简化操作。
  2. Symfony 验证器集成:
    利用 Symfony 内置的验证器来确保数据完整性并符合您的验证规则。
  3. 嵌套 DTO 支持:
    通过支持查询和正文参数的嵌套 DTO,简化了复杂请求结构的处理,便于管理层次数据。

安装

composer crtl/request-dto-resolver-bundle

配置

在您的 Symfony 应用程序中注册此扩展包。请将以下内容添加到您的 config/bundles.php 文件中

return [
    // other bundles
    Crtl\RequestDTOResolverBundle\CrtlRequestDTOResolverBundle::class => ["all" => true],
];

用法

步骤 1:创建 DTO

创建一个表示请求数据的类。使用 #[RequestDTO] 注解该类,并使用以下属性将请求参数映射到属性上。

namespace App\DTO;

use Crtl\RequestDTOResolverBundle\Attribute\BodyParam;
use Crtl\RequestDTOResolverBundle\Attribute\FileParam;
use Crtl\RequestDTOResolverBundle\Attribute\HeaderParam;
use Crtl\RequestDTOResolverBundle\Attribute\QueryParam;
use Crtl\RequestDTOResolverBundle\Attribute\RouteParam;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Constraints as Assert;

#[RequestDTO]
class ExampleDTO
{
    // Matches someParam in request body
    #[BodyParam, Assert\NotBlank]
    public ?string $someParam;

    // Matches file in uploaded files
    #[FileParam, Assert\NotNull]
    public mixed $file;
    
    // Matches Content-Type header in headers
    #[HeaderParam("Content-Type"), Assert\NotBlank]
    public string $contentType;
    
    // Pass string to param if property does not match param name.
    // Matches queryParamName in query params
    #[QueryParam("queryParamName"), Assert\NotBlank]
    public string $query;

    // Matches id 
    #[RouteParam, Assert\NotBlank]
    public string $id;
    
    // Nested DTOs are supported for BodyParam and QueryParam
    #[BodyParam("nested"), Assert\Valid]
    public ?NestedRequestDTO $nestedBodyDto;
    
    #[QueryParam("nested")]
    public ?NestedRequestDTO $nestedQueryParamDto;
    
    // Optionally implement constructor which accepts request object
    public function __construct(Request $request) {
    
    }
}

重要提示
除了请求 DTO 的属性外,每个属性都必须接受 ?string 类型。
否则,PHP 可能会在运行时抛出 TypeError,因为我们无法在验证之前知道请求是否包含有效的数据类型。

默认情况下,每个参数都会通过其属性名称解析。
如果属性名称与参数名称不匹配,您可以为每个 *Param 属性的构造函数传递一个可选的字符串(见 AbstractParam::__construct)。

每个 DTO 可以定义一个可选的构造函数,该构造函数接受一个 Request 对象

步骤 2:在控制器中使用 DTO

将 DTO 注入到您的控制器动作中。RequestValueResolver 将自动实例化和验证 DTO。

namespace App\Controller;

use App\DTO\ExampleDTO;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ExampleController extends AbstractController
{
    #[Route("/example", name: "example")]
    public function exampleAction(ExampleDTO $data): Response
    {
        // $data is an instance of ExampleDTO with validated request data
        return new Response("DTO received and validated successfully!");
    }
}

步骤 3:处理验证错误

当验证失败时,会抛出 Crtl\RequestDTOResolverBundle\Exception\RequestValidationException

您可以创建事件监听器或覆盖默认的异常处理程序来处理验证错误。

namespace App\EventListener;

use Crtl\RequestDTOResolverBundle\Exception\RequestValidationException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;

class RequestValidationExceptionListener implements EventSubscriberInterface
{

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::EXCEPTION => "onKernelException",
        ];
    }

    public function onKernelException(ExceptionEvent $event)
    {
        $exception = $event->getThrowable();

        if ($exception instanceof RequestValidationException) {
            $response = new JsonResponse([
                "error" => "Validation failed",
                "details" => $exception->getViolations(),
            ], JsonResponse::HTTP_BAD_REQUEST);

            $event->setResponse($response);
        }
    }
}

许可

此扩展包受 MIT 许可证许可。有关更多详细信息,请参阅 LICENSE 文件。