nikita2206 / symfony-request-converter
请求转换器将请求数据转换为数据对象
Requires
- doctrine/annotations: ^1.2
- sensio/framework-extra-bundle: ^2.5 || ^3
- symfony/config: ^2.5 || ^3
- symfony/dependency-injection: ^2.5 || ^3
- symfony/http-kernel: ^2.5 || ^3
- symfony/validator: ^2.5 || ^3
Requires (Dev)
This package is not auto-updated.
Last update: 2023-06-10 12:06:08 UTC
README
将API请求从纯PHP数组转换为请求对象。
示例
在您的控制器操作中,您可以使用
public function addBlogPostAction(PostRequest $post) { $this->commandBus->execute(new NewPost($post)); }
请求将自动从纯数组形式转换为PostRequest
类实例(不调用构造函数创建)并进行验证
use RequestConverter\Annotation\Type; use RequestConverter\Annotation\Optional; use RequestConverter\Annotation\Request; /** * We need to use this annotation in order to tell request converter that it should pick up action * parameter type-hinted with this class * @Request() **/ class PostRequest { /** * @Type("string") **/ private $title; /** * @Type("string") **/ private $text; /** * @Type("string") * @Optional() **/ private $author; }
如何设置
在您的composer.json
中引入nikita2206/symfony-request-converter
之后,您需要注册异常监听器以渲染RequestConverter\Exception\BadRequestException
,如果请求无效则将抛出此异常。
这是该监听器的基本示例,您当然希望使其符合您的API错误规范。或者,作为一个更好的解决方案,可以将错误渲染委托给另一个控制器,就像在Symfony\Component\HttpKernel\EventListener\ExceptionListener
中做的那样。
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use RequestConverter\Exception as Ex; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; class ExceptionListener { public function onKernelException(GetResponseForExceptionEvent $event) { if ( ! $event->getException() instanceof Ex\BadRequestException) { return; } $errors = []; // this exception is thrown when there was a problem while mapping input data on the object: // * missing field // * incompatible type (string when array is expected f.e.) // * uncoercible value (string "45zz" when integer is expected) if ($event->getException() instanceof Ex\RequestConversionException) { foreach ($event->getException()->getErrors() as $err) { $errors[] = ["field" => $err->getField(), "kind" => get_class($err)]; } // this exception is the result of symfony/validation component, it has ConstraintViolationListInterface } elseif ($event->getException() instanceof Ex\RequestValidationException) { foreach ($event->getException()->getViolations() as $v) { $errors[] = ["field" => $v->getPropertyPath(), "kind" => $v->getMessage()]; } } $event->setResponse(new Response(\json_encode($errors), 400)); } }
如何使用
所有根请求类都需要标记为RequestConverter\Annotation\Request
注解。并且该请求类中的每个成员都可以标记为RequestConverter\Annotation\Type
注解,以强制将其转换为该类型。下面是所有可能类型的参考。您还可以使用RequestConverter\Annotation\Optional
注解来忽略请求有效载荷中字段的缺失。
默认情况下,RequestConverter将使用请求体,但您可以将它切换为使用查询来获取某些操作参数。为此,您需要使用Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter
注解并使用options={"query"=true}
参数,如下所示
/**
* @ParamConverter("filter", options={"query"=true})
*/
public function filterPostsAction(Filter $filter)
{
}
类型注解
您可以使用几种类型,这些类型包括:int、bool、float、string、array、map以及类名。如果传入的数据不是正确的类型,我们将尝试将其转换,以下是一个可能的类型列表及其与其他类型的转换兼容性。
Int类型
除了int
外,它还可以接受表示整数的数值string
。否则,如果它是文本字符串或表示浮点数,您将获得UncoercibleValueError
。
Bool类型
也可以接受int
、float
和string
。对于int
和float
以及数值字符串,将产生false
(对于0)和true
(对于所有其他数字)。对于非数值字符串,它将首先尝试将它们与预设值[yes, true, Y, T]
和[no, false, N, F]
进行比较,如果未找到匹配项,它将静默地将字符串转换为(bool)$value
。
浮点类型
也可以接受 int
和 string
。如果字符串表示浮点数或整数,则尝试将字符串强制转换为 float
。
字符串类型
接受 string
、int
和 float
,并将其转换为 string
。
数组类型
仅接受数组。
此类型是参数化的:对于 T
的数组,可以使用 array<T>
语法(类似于流行语言中的泛型语法)。如果 T
是类名,它将被映射和验证。
映射类型
仅接受数组。
此类型是参数化的,有两个重载:Map<V>
和 Map<K, V>
。类型参数 K
只能是 string
或 int
。
类名类型
如果你在 RequestConverter\Annotation\Type
注解中使用自己的类名或将其作为 array
或 Map
类型的参数,RequestConverter 将尝试将输入数据映射到该类的新创建的对象。
验证
你还可以使用 symfony/validator
组件的验证约束。如果没有错误,则应用验证器,默认为验证组。
扩展 RequestConverter
你可以添加自己的数据类型,用于与 Type
注解和参数化类型一起使用 - 为此,你需要创建一个 RequestConverter\Coercion\TypeCoercer
接口的新实现,并在 RequestConverter\Coercer
服务中注册它。目前此服务不可配置,因此你必须使用 Symfony DI 的服务定义覆盖功能,覆盖 request_converter.coercer
服务的定义。
贡献
欢迎所有类型的贡献:文档、代码或测试。项目主要遵循 PSR-2 风格指南。
你可以从项目的根目录运行测试,使用 ./vendor/bin/phpunit
命令。