metglobal / dto-bundle
symfony应用程序的数据传输对象库
Requires
- php: >=7.0
- doctrine/annotations: ~1.0
- sensio/framework-extra-bundle: ~5.0
- symfony/http-foundation: ^3.4|^4.4|^5.0
- symfony/options-resolver: ^3.4|^4.4|^5.0
- symfony/property-access: ^3.4|^4.4|^5.0
Requires (Dev)
- symfony/phpunit-bridge: ^4.2
README
此bundle专注于将请求参数注入数据传输对象。
安装
确保已全局安装Composer,如Composer文档中的安装章节所述。
使用Symfony Flex的应用程序
打开命令行,进入您的项目目录并执行
$ composer require metglobal-compass/dto-bundle
不使用Symfony Flex的应用程序
步骤1:下载bundle
打开命令行,进入您的项目目录并执行以下命令以下载此bundle的最新稳定版本
$ composer require metglobal-compass/dto-bundle
步骤2:启用bundle
然后,通过将其添加到项目config/bundles.php
文件中注册的bundle列表来启用bundle
// config/bundles.php return [ // ... Metglobal\DTOBundle\DTOBundle::class => ['all' => true], ];
步骤3:启用param converter
Metglobal\DTOBundle\DTOParamConverter: tags: - { name: request.param_converter, priority: -2, converter: dto_converter }
如何使用
定义一个控制器方法参数,带有类型提示。类型提示必须是\Metglobal\Compass\Domain\DTO\Request
的实例。如果是symfony,将尝试使用默认配置解析参数。使用\Metglobal\DTOBundle\DTOParamConverter
。
见:\Metglobal\DTOBundle\DTOParamConverter::supports
。
默认参数解析器参数(见:\Metglobal\DTOBundle\OptionsResolver\ParameterOptionsResolver
,\Metglobal\DTOBundle\OptionsResolver\DateParameterOptionsResolver
)
[ 'type' => 'string', 'scope' => 'request', 'disabled' => false, 'options' => [], 'undefined' => false ]
属性注释示例
@Metglobal\Compass\Annotation\DTO\Parameter(
type="string",
scope="request",
path="pathOfThisParameter",
disabled=false,
options={},
undefined=false
)
可用的属性注释选项
转换器会自动尝试使用默认值解析所有内容,但您可以使用Metglobal\Compass\Annotation\DTO\Parameter
注释配置以下参数,并且如果没有为属性定义此注释,它也会尝试解析自身。
type
变量的类型。可用类型有:'string', 'boolean', 'bool', 'integer', 'int' 和 'mixed'。混合类型允许您将任何类型的值应用于属性。
注意:布尔类型是例外,见:\Symfony\Component\HttpFoundation\ParameterBag::getBoolean
。
scope
变量的作用域。可用的作用域有:'request', 'query', 'headers', 'attributes'
path
变量的路径。默认情况下是属性名,但您可以自定义变量的路径。示例:URL: *.com?testPath=3
/** * @Parameter(scope="query", path="testPath") */ public $differentName;
它将3赋值给$differentName。
警告:如果您未定义此参数,则需要按属性进行设置。这意味着在上面的示例中,路径将是differentName
。
disabled
禁用所选参数的注入。
options
format:
-------
Available when you set type to date. You can configure input datetime's format with this property.
timezone:
--------
Available when you set type to date. You can configure datetime's timezone with this property.
undefinedable
使属性可未定义。此属性使您能够找到未定义的属性。
额外注释提示
此注释可以在属性或类中使用。如果您将此属性定义为类,则它将影响所有类的属性。
Default parameters overrides --> Class annotation parameters (If exists) overrides --> Property annotation parameters (If exists)
对于每个参数,它将调用一个找到每个属性最终注入配置的方法 按属性。示例
<?php namespace Metglobal\Compass\Request; use Metglobal\DTOBundle\Annotation\Parameter; use Metglobal\DTOBundle\Request; use Metglobal\DTOBundle\Undefined; /** * @Parameter(scope="query") */ class DummyRequest implements Request { /** * @Parameter(type="int") * * @var int|null */ public $foo; /** * @Parameter(type="int") * * @var int|null */ public $bar; }
在上面的类中,$foo将注入来自query作用域,而$bar将注入到具有整数类型转换的query中。
空/未定义变量
每个已定义但没有默认值的属性都是可空的,可以是未定义的。
警告:如果您为属性定义了默认值,转换器将注入默认值而不是null。
示例
namespace Metglobal\Compass\Request; use Metglobal\DTOBundle\Annotation\Parameter; use Metglobal\DTOBundle\Request; use Metglobal\DTOBundle\Undefined; class DummyRequest implements Request { /** * @Parameter(scope="query", undefined=true) * * @var string|null|Undefined */ public $foo; }
结果将是
?foo= | ?foo=bar | ?baz=5 |
---|---|---|
null | "bar" | Undefined() |
生命周期事件
\Metglobal\DTOBundle\Annotation\PreSet
将此注释定义在方法上允许您在将请求参数设置到目标类之前访问属性 之前。
\Metglobal\DTOBundle\Annotation\PostSet
将此注释定义在方法上允许您在将请求参数设置到目标类之后访问属性 之后。
The \Metglobal\DTOBundle\CallableRequest interface
您应该使用上述配置通过@Metglobal\Compass\Annotation\DTO\Parameter
注释注入所有简单参数,但如果存在注释无法处理的复杂逻辑,则可以使用此接口作为回调方法。
在call()
方法中,您可以使用...$args
变量修改对象的属性。提示1:推荐的基本处理方法是使用生命周期事件。只有当您需要将内容注入目标类时才使用此接口。提示2:如果您不知道...$args
的含义,请参阅RFC:https://wiki.php.net/rfc/argument_unpacking。
示例用法
控制器
<?php namespace Metglobal\Compass\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; ... class DummyController extends Controller { /** * @Route("/dummy/{id}", requirements={"id" = "\d+"}, methods={"DELETE"}, name="dummy_route") */ public function __invoke(FooService $fooService, BarService $barService, BazService $bazService, DummyRequest $request): JsonResponse { $request->call($fooService, $barService); return new JsonResponse($bazService->handle($request)); } }
请求
<?php namespace Metglobal\Compass\Request; use Metglobal\DTOBundle\Annotation\Parameter; use Metglobal\DTOBundle\Annotation\PostSet; use Metglobal\DTOBundle\Annotation\PreSet; use Metglobal\DTOBundle\CallableRequest; use Metglobal\DTOBundle\Undefined; /** * @Parameter(scope="query") */ class DummyRequest implements CallableRequest { /** * @Parameter(type="int") * * @var int|null */ public $foo; public $bar; public $baz; /** * @var \DateTime|null * * @Parameter(type="date", options={format="Y-m-d"}) */ public $fooBar; public function call(...$args) { [ $fooService, $barService ] = $args; $this->foo = $fooService->aMethod($barService->bMethod($this->foo)); } /** * This method will run before setting the parameters * * @PreSet() */ public function preSetXMethod(){ $this->baz = 1; } /** * This method will run after setting the parameters * * @PostSet() */ public function postSetXMethod(){ $this->baz = 5; } }
分组
您可以使用@Metglobal\DTOBundle\Annotation\Group
注释对注入的属性进行分组。
示例
<?php namespace Metglobal\Compass\Request; use Metglobal\DTOBundle\Annotation\Parameter; use Metglobal\DTOBundle\CallableRequest; use Metglobal\DTOBundle\Undefined; /** * @Group("fooGroup") * @Parameter(scope="query") */ class DummyRequest implements CallableRequest { /** * @Parameter(type="int", undefined=true) * @Group(target="barGroup") * * @var int|null|Undefined */ public $foo; /** * @Group(disabled=true) */ public $bar; public $baz; /** @var array */ public $fooGroup; }
查询: ?foo=fooValue&bar=barValue&baz=bazValue&exampleGroup=bug&nextGroup=bug
$fooGroup
将会是
[ 'baz' => 'bazValue', ];
$barGroup
将会动态定义
[ 'foo' => 'fooValue', ];
可用的组注释选项
您可以在类上使用此注释(它将对每个属性应用组选项),或者在属性
目标
目标组变量。无论目标是否定义,转换器都会将变量放入指定的目标。
禁用
您仍然可以使用属性注入,但它将禁用属性或整个类的分组。
重要注意事项
- 组属性不可注入
- 组注释可用于类或属性
- 您可以使用
@Metglobal\DTOBundle\Annotation\PostSet
事件修改组 - 如果您禁用了属性注入(
@Metglobal\DTOBundle\Annotation\Parameter(disabled=true)
),它也会将属性放入组中。要禁用,请将组的disabled
选项设置为 true。
贡献
如果您遇到问题、发现错误或提出功能建议,请登录 Github 并提交问题。如果您想亲自尝试,请fork该包并提交拉取请求。请包括任何添加或更改的功能的测试。如果是错误,请包括回归测试。