acsiomatic/http-payload-bundle

dev-main 2023-04-07 16:46 UTC

This package is auto-updated.

Last update: 2024-09-07 19:48:59 UTC


README

acsiomatic/http-payload-bundle 处理 HTTP 负载,在 路由 中表现像 API 端点,这些路由在 Symfony 应用程序中使用。

特性简述

MapRequestBody 是一个控制器参数 属性,它

  1. 将传入的 HTTP 请求体 转换为一个 对象
  2. 使用 Symfony 验证 验证对象
  3. 将对象注入到 路由 参数中

MapUploadedFile 是一个控制器参数 属性,它

  1. 从传入的 上传文件 对象中提取 UploadedFile 对象
  2. 使用 文件约束 验证对象
  3. 将对象注入到 路由 参数中

ResponseBody 是一个路由 属性,它

  1. 通过 内容协商 寻找合适的响应格式
  2. 序列化 被调用的路由返回的数据
  3. kernel.controller 事件之后抛出的异常也将被序列化
  4. 将序列化后的数据注入到 响应 对象中

安装

composer require acsiomatic/http-payload-bundle

配置

# config/packages/acsiomatic_http_payload.yaml

acsiomatic_http_payload:
    request_body:
        default:
            formats: ['json']
            deserialization_context: []
            validation_groups: ['Default']
    file_upload:
        default:
            constraints: []
    response_body:
        default:
            formats: ['json']
            serialization_context: []

使用场景

接收对象

MapRequestBody 属性将 HTTP 请求体 注入到 路由 参数中。传入的数据在注入之前将被 反序列化验证

# src/Controller/LuckyController.php

namespace App\Controller;

use Acsiomatic\HttpPayloadBundle\RequestBody\Attribute\MapRequestBody;
use App\NumberRange;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
final class LuckyController
{
    #[Route('/lucky/number', methods: ['GET'])]
    public function number(
        #[MapRequestBody] NumberRange $range,
    ): Response {
        return new Response(
            (string) random_int($range->min, $range->max)
        );
    }
}
# src/NumberRange.php

namespace App;

use Symfony\Component\Validator\Constraints as Assert;

final class NumberRange
{
    #[Assert\GreaterThanOrEqual(0)]
    public int $min;

    #[Assert\GreaterThanOrEqual(propertyPath: 'min')]
    public int $max;
}

接收文件

MapUploadedFile 属性从 Request 中获取文件,并在将其注入到 Route 参数之前应用 自定义约束

# src/Controller/UserController.php

namespace App\Controller;

use Acsiomatic\HttpPayloadBundle\FileUpload\Attribute\MapUploadedFile;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Constraints\File;

#[AsController]
final class UserController
{
    #[Route('/user/picture', methods: ['PUT'])]
    public function picture(
        #[MapUploadedFile(
            constraints: new File(mimeTypes: ['image/png', 'image/jpeg']),
        )] UploadedFile $picture,
    ): Response {
        return new Response('Your picture was updated');
    }
}

返回对象

ResponseBody 属性将 Route 返回的对象 序列化,并用它填充 Response 的内容。

# src/Controller/CelebritiesController.php

namespace App\Controller;

use Acsiomatic\HttpPayloadBundle\ResponseBody\Attribute\ResponseBody;
use App\Person;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
final class CelebritiesController
{
    #[Route('/celebrities/einstein', methods: ['GET'])]
    #[ResponseBody]
    public function einstein(): Person
    {
        $person = new Person();
        $person->name = 'Albert Einstein';
        $person->birthdate = new \DateTimeImmutable('1879-03-14');

        return $person;
    }
}
# src/Person.php

namespace App;

use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;

final class Person
{
    public string $name;

    #[Serializer\Context([DateTimeNormalizer::FORMAT_KEY => \DateTimeInterface::ATOM])]
    public \DateTimeImmutable $birthdate;
}

返回文件

参见 流式文件响应