Symfony 4扩展了验证请求

时间:2018-09-12 08:02:01

标签: php validation symfony4

我目前正在从事API项目。我已经习惯了Laravel,现在我需要与Symfony合作。我想像Laravel一样使用该请求进行验证。 因此,我扩展了Symfony \ Component \ HttpFoundation \ Request类。在那里,我提出了一些逻辑来检查和清理传入的请求。

之后,我将新创建的请求添加到控制器中的store函数。但这给了我一个错误:

Argument 1 passed to App\Controller\Ticket\TicketController::store() must be an instance of App\Validation\Ticket\TicketStoreRequest, instance of Symfony\Component\HttpFoundation\Request given,/vendor/symfony/http-kernel/HttpKernel.php on line 149 {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Argument 1 passed to App\\Controller\\Ticket\\TicketController::store() must be an instance of App\\Validation\\Ticket\\TicketStoreRequest, instance of Symfony\\Component\\HttpFoundation\\Request given

在谷歌搜索后,我发现了一些选择。

  1. 将每个控制器操作添加到service.yaml
  2. 创建一个侦听器并在正确的路由上添加验证

但是所有选项都需要在其他地方的其他信息。我希望有人有更好的主意。

2 个答案:

答案 0 :(得分:1)

我发现了一些提示,可能会为您指明正确的方向:

  

Symfony在HttpKernel组件中附带五个值解析器:

     

...

     

RequestValueResolver

     

如果使用Request或扩展Request的类进行提示,则注入当前Request。

请参阅https://symfony.com/doc/current/controller/argument_value_resolver.html

然后,该页面继续描述自定义RequestAttributeValueResolver的实现。此自定义解析器可以在您的计算机中注册 services.yml。 尽管在此示例中,为一个单一属性类型(用户)创建了一个类,但仍有一些方法可以创建更动态的实现。

在此示例中,ArgumentMetadata参数具有方法$argument->getType(),该方法应包含要检查的类型的字符串表示形式:

if (User::class !== $argument->getType()) {
    return false;
}

没有什么可以阻止您检查支持的请求类型数组。您可以在自定义RequestValueResolver中将此数组作为类成员进行管理。您的自定义RequestValueResolver类的唯一要求是,supports()方法返回受支持的请求类型的true,并且resolve()函数返回此受支持的请求类型的实例。这应该很简单,因为通过ArgumentMetaData参数为这两种方法提供了“所需”类。

或者,您可以为要支持的每种自定义请求类型实现自定义RequestValueResolver,但这并不十分优雅。

我不能保证这会成功,并且我也不确定在示例中实现RequestAttributeValueResolver和实现自定义RequestValueResolver之间的区别,但是我有感觉可能会起作用,加上一点肘油脂。

以供参考:https://api.symfony.com/4.1/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestValueResolver.html

答案 1 :(得分:0)

以下是详细说明我的另一个示例的解决方案。它不像我的其他示例那样安全,但是可以满足您的要求。

public function supports(Request $request, ArgumentMetadata $argument)
{    
    $desiredRequestClass = $argument->getType();

    return class_exists($desiredRequestClass);
}

public function resolve(Request $request, ArgumentMetadata $argument)
{
    $desiredRequestClass = $argument->getType();
    $customRequest = new $desiredRequestClass();

    $customRequest->createFromGlobals();
    // TODO: more initialization you might need.

    yield $customRequest;
}

建议检查$desiredRequestClass是否为Request的后代。