pitch / symfony-adr
此包使得在编写Symfony应用程序时遵循ADR模式变得更加容易
Requires
- php: >=7.4
- composer/composer: ^1 || ^2
- pitch/annotation: ^1.0
- symfony/config: ^5.4.9 || ^6
- symfony/dependency-injection: ^5.4.9 || ^6
- symfony/http-kernel: ^5.4.9 || ^6
Requires (Dev)
- doctrine/annotations: ^1.12
- mikey179/vfsstream: ^1.6.10
- phpunit/phpunit: ^9.5.21
- squizlabs/php_codesniffer: ^3.7.1
- symfony/framework-bundle: ^5.4.9 || ^6
This package is auto-updated.
Last update: 2024-09-20 19:35:16 UTC
README
此包使得在编写 Symfony 应用程序时遵循ADR模式变得更加容易。
用法
将控制器转换为动作
通过将响应者逻辑从动作逻辑中分离出来,将其移出控制器。只需返回有效载荷即可!
如果控制器返回的不是 Response
对象,Symfony将触发一个kernel.view
事件。
现在,您不必注册大量事件监听器进行迭代,只需实现 ResponseHandlerInterface
。
namespace App\Responder; use Pitch\AdrBundle\Responder\ResponseHandlerInterface; use Pitch\AdrBundle\Responder\ResponsePayloadEvent; use Symfony\Component\HttpFoundation\Response; use App\Entity\MyPayload; class MyPayloadHandler implements ResponseHandlerInterface { public function getSupportedPayloadTypes(): array { return [ MyPayload::class, ]; } public function handleResponsePayload( ResponsePayloadEvent $payloadEvent ): void { $response = new Response(); // prepare the response if ($payloadEvent->request->getAttribute('_foo') === 'bar') { // adjust the response according to the request } $payloadEvent->payload = $response; } }
如果您的处理类根据您的 config/services.yaml
作为服务可用,它将在控制器返回 MyPayload
对象时被发现和使用。
默认配置下,只需将类放入 src/Responder/MyPayloadHandler.php
即可。
您可以在 getSupportedTypes
中报告您的响应处理器的优先级。
class MyPayloadHandler implements ResponseHandlerInterface { public function getSupportedPayloadTypes(): array { return [ MyPayload::class => 123, MyOtherPayload:class => 456, ]; } //... }
或者,您可以在 services.yml
中覆盖响应处理器的处理类型和优先级。
services: App\Responder\MyPayloadHandler: tags: - name: pitch_adr.responder for: [App\Entity\MyPayload] priority: 1000 - name: pitch_adr.responder for: [App\Entity\MyOtherPayload] priority: 0
您可以通过控制台命令轻松调试响应器配置。
$ php bin/console debug:responder MyPayload
将一些异常作为响应有效载荷处理
一个健壮的领域将有严格的约束,并在发生任何意外或无效条件时抛出异常,并且对于所有通过控制器/动作传递的异常,Symfony都会触发一个kernel.exception
事件。
您可以将此事件保留用于真正意外的行为,而无需在控制器中重复类似的try-catch块。
定义所有控制器应该捕获哪些异常并将其作为响应有效载荷处理
pitch_adr: graceful: - { value: RuntimeException, not: [BadRuntime, OtherBadRuntime] } - Foo - { not: GloballyBadException } - { value: Bar, not: BadBar }
如果已安装Doctrine Annotations,则可以为控制器方法定义额外的规则
namespace App\Controller; use Pitch\AdrBundle\Configuration\Graceful; class MyController { /** * @Graceful(not=LocallyBadException::class) * @Graceful(LocallyGoodException::class, not={ButNotThisOne::class, OrThatOne::class}) */ public function __invoke( Request $request ) { /// ... } }
使用PHP8,您可以按属性定义每个方法的额外规则
namespace App\Controller; use Pitch\AdrBundle\Configuration\Graceful; class MyController { #[Graceful(not: LocallyBadException::class)] #[Graceful(LocallyGoodException::class, not: [ButNotThisOne::class, OrThatOne::class])] public function __invoke( Request $request ) { /// ... } }
规则按出现顺序应用,方法规则在全局规则之后。
现在,您可以创建一个 App\Responder\MyGoodRuntimeExceptionHandler
,如上所述。
默认响应处理器
该包自动为基本类型添加了一些响应处理器,具有负优先级,以便在您的响应处理器中未停止传播之前调用它们。如果您不想添加默认处理器,可以按包配置修改此行为。
pitch_adr: defaultResponseHandlers: false # defaults to true
优先级响应处理器
如果连续的响应处理器(按配置优先级顺序)实现了 PrioritisedResponseHandlerInterface
,则该处理器块将在运行时根据它们在getResponseHandlerPriority
中报告的特定请求优先级进行排序。
Given the following response handlers are configured to handle a `SomePayloadType`:
900: HandlerA
600: PrioritisedHandler1 with getResponseHandlerPriority(): 1
500: PrioritisedHandler2 with getResponseHandlerPriority(): 2
400: PrioritisedHandler3 with getResponseHandlerPriority(): 0
100: HandlerB
these will be executed in the following order:
HandlerA
PrioritisedHandler2
PrioritisedHandler1
PrioritisedHandler3
HandlerB
在响应处理器中协商内容类型
有关如何实现自己的优先级响应处理器,该处理器根据请求中的 Accept 头处理有效载荷,请参阅 JsonResponder
。
您可以为不包含Accept头的请求设置默认内容类型。这可以通过容器参数或控制器注释来完成。
parameters: pitch_adr.defaultContentType: 'application/json'
use Pitch\AdrBundle\Configuration\DefaultContentType; class MyController { #[DefaultContentType('application/json')] public function __invoke() { // ... } }