deadmansswitch / 响应者
响应者组件,适用于 Symfony 应用程序
0.1.5
2024-08-31 07:26 UTC
Requires
- php: ~8.1.0||~8.2.0||~8.3.0
- ext-json: *
- symfony/dependency-injection: ^6.0|^7.0
- symfony/framework-bundle: ^6.0|^7.0
- symfony/http-foundation: ^6.0|^7.0
- symfony/http-kernel: ^6.0|^7.0
- symfony/property-access: ^6.0|^7.0
- symfony/serializer: ^6.0|^7.0
Requires (Dev)
- mockery/mockery: ^1.6
- pestphp/pest: ^2.35
- spatie/ray: ^1.41
- symfony/uid: ^6.0|^7.0
README
快速开始:将您的传统 MVC symfony 应用转换为 ADR 应用
特性
从动作返回类型化响应
您可以从控制器返回 DTO 对象,而不是返回 Response 对象。
之前
<?php declare(strict_types=1); namespace App\Controller; use App\DTO\CreateUserInput; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; #[Route('/users', name: 'create_user', methods: ['POST'])] final class UserController extends AbstractController { public function __invoke(#[MapRequestPayload] CreateUserInput $input): Response { $user = new User(); $user->setLogin($request->get('name')); $user->setEmail($request->get('email')); $user->setPassword($request->get('email')); // ... some logic, entity validation, password hashing, persisting etc. (delegate it to service in real app) return new JsonResponse(['id' => $user->getId()], Response::HTTP_CREATED); } }
之后
<?php declare(strict_types=1); namespace App\Controller; use App\DTO\CreateUserInput; use App\DTO\CompactUserDTO; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; #[Route('/users', name: 'create_user', methods: ['POST'])] final class CreateUser { public function __invoke(#[MapRequestPayload] CreateUserInput $input): CompactUserDTO { $user = new User(); $user->setLogin($input->login); $user->setEmail($input->email); $user->setPassword($input->password); // ... some logic, entity validation, password hashing, persisting etc. (delegate it to service in real app) return new CompactUserDTO( id: $user->getId(), login: $user->getLogin(), createdAt: $user->getCreatedAt(), ); } }
好处
- 客户端代码量略有减少,无需在每个控制器中注入序列化器
- 业务逻辑与响应格式化分离,因此动作可重用
- 每个动作现在都有一个清晰的返回对象合同
- 能够通过反射读取动作并生成 API 文档
自动响应序列化
使用内容类型协商,该包将为客户端目的创建适当的 Responder 实例来序列化您的数据。
默认情况下,您就有 JsonResponder,它将您的 DTOs 序列化为 JSON 响应。
您可以为不同的内容类型创建自己的响应者,或者用自定义实现覆盖默认的 JsonResponder。
HTTP 响应码
它为每个 HTTP 请求方法使用默认响应码,但您可以在动作级别轻松覆盖它们
<?php declare(strict_types=1); namespace App\Domain\User\Action; #[HttpResponseCode(status: 202)] // <----------- 202 Accepted instead of 201 Created final class CreateUser { public function __invoke(CreateUserInput $input): CreateUserOutput { // ... } }