简体   繁体   English

Symfony 验证器服务和设置器中的 TypeErrors

[英]Symfony validator service and TypeErrors in setters

I'm currently confused by the way the Symfony validator service works.我目前对 Symfony 验证器服务的工作方式感到困惑。 The way I currently understand it, it could completely fail and not report errors even before it can even validate an entity if a TypeError occurs while setting values.按照我目前的理解,如果在设置值时发生 TypeError,它甚至可以在验证实体之前完全失败并且不会报告错误。

The Symfony documentation uses Constraints in entities like this: Symfony 文档在这样的实体中使用约束:

namespace App\Entity;

// ...
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    /**
     * @Assert\NotBlank
     */
    private $name;
}

Which are then used like this in the controllers:然后在控制器中像这样使用它们:

public function author(ValidatorInterface $validator)
{
    $author = new Author();
    
    // ... do something to the $author object

    $author->setBirthDate('this will fail and not report'); // I added this line in myself, see rest of question.
  

    $errors = $validator->validate($author);

    if (count($errors) > 0) {
        /*
         * Uses a __toString method on the $errors variable which is a
         * ConstraintViolationList object. This gives us a nice string
         * for debugging.
         */
        $errorsString = (string) $errors;

        return new Response($errorsString);
    }

    return new Response('The author is valid! Yes!');
}

However, this will not nicely catch the exceptions that will be thrown when arguments of the wrong type are passed towards the setters of the entity variables.但是,当错误类型的 arguments 被传递给实体变量的设置器时,这不会很好地捕获将引发的异常。 For example, the entity could have a field "birthDate" which is a DateTime, and which has a setter setBirthDate(DateTime $foo).例如,实体可以有一个字段“birthDate”,它是一个 DateTime,并且有一个 setter setBirthDate(DateTime $foo)。 When building the object before being able to call the validate() function, one could pass an argument of an incorrect type - say, the user submitted a string or nothing at all - which will obviously raise an exception.在能够调用 validate() function 之前构建 object 时,可能会传递类型不正确的参数 - 例如,用户提交了一个字符串或根本没有提交 - 这显然会引发异常。

Assuming that the validator service is supposed to be used like this, my question is as follows: how do I cleanly handle the data which could raise TypeErrors in the setters?假设验证器服务应该像这样使用,我的问题如下:我如何干净地处理可能在设置器中引发 TypeErrors 的数据?

Do I not do any type hinting in my setters (accepting everything) and then validate it being a DateTime with the validator later on?我是否不在我的设置器中进行任何类型提示(接受所有内容),然后稍后使用验证器验证它是 DateTime 吗? Do I use a try/catch block while setting up the entity?设置实体时是否使用 try/catch 块? Do I manually check the type of the user input before calling the setter?在调用 setter 之前,我是否要手动检查用户输入的类型? And if any of the last two, how would I cleanly report errors to the user?如果最后两个中的任何一个,我将如何干净地向用户报告错误? And even then, I think it would feel wrong to also be doing manual validation there when you're also doing it in the validator service.即便如此,我认为当您也在验证器服务中进行手动验证时,在那里进行手动验证会感觉不对。

I know about Forms and I assume this is not an issue when using those, but I still find the validator confusing either way.我知道 Forms 并且我认为在使用它们时这不是问题,但我仍然发现验证器无论哪种方式都令人困惑。

You are missing the point of how the code should work, if you specify that the setter will accept DateTime object and DateTime object only PHP itself will ensure that the accepted argument is an instance of DateTime object. You are missing the point of how the code should work, if you specify that the setter will accept DateTime object and DateTime object only PHP itself will ensure that the accepted argument is an instance of DateTime object. One way to go around that is to create a DTO(Data transfer object) eg. go 的一种方法是创建一个 DTO(数据传输对象),例如。 CreateAuthorRequest and create a symfony form type where you accept either string/DateTime(preferably string which will have a regex ensuring that the string is a valid datetime string). CreateAuthorRequest 并创建一个 symfony 表单类型,您可以在其中接受字符串/日期时间(最好是字符串,它有一个正则表达式,确保字符串是有效的日期时间字符串)。 Then after you call $form->isValid() you can read the data from the DTO and be sure that it's valid.然后在您调用$form->isValid()之后,您可以从 DTO 读取数据并确保它是有效的。 If you'll still struggle how this should be implemented correctly comment below the answer and I'll provide code samples如果您仍然难以正确实施,请在答案下方评论,我将提供代码示例

Also I wouldn't recommend to put that much annotations in your entity it will get messy pretty quick, prefer XML config over annotations.此外,我不建议在您的实体中放置那么多注释,它会很快变得混乱,更喜欢 XML 配置而不是注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM