我目前对Symfony验证器服务的工作方式感到困惑。按照我目前的理解,如果在设置值时发生TypeError,它可能会完全失败,甚至在验证实体之前都不会报告错误。
Symfony文档在以下实体中使用约束:
namespace AppEntity;
// ...
use SymfonyComponentValidatorConstraints as Assert;
class Author
{
/**
* @AssertNotBlank
*/
private $name;
}
然后在控制器中像这样使用:
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!');
}
然而,当错误类型的参数被传递给实体变量的setter时,这不会很好地捕捉到将抛出的异常。例如,实体可以具有字段"0";出生日期";其是DateTime并且具有setter setBirthDate(DateTime$foo(。在调用validate((函数之前构建对象时,可能会传递一个类型不正确的参数——比如说,用户提交了一个字符串或什么都不提交——这显然会引发异常。
假设验证程序服务应该这样使用,我的问题如下:如何干净地处理可能在setters中引发TypeErrors的数据?
我是否不在setters中进行任何类型提示(接受所有内容(,然后稍后用验证器验证它是否为DateTime?设置实体时是否使用try/catch块?在调用setter之前,我是否手动检查用户输入的类型?如果是后两种情况中的任何一种,我将如何向用户干净地报告错误?即便如此,我认为也在验证器服务中进行手动验证是错误的。
我知道Forms,我认为在使用这些表单时这不是一个问题,但我仍然发现验证器在任何方面都很困惑。
如果您指定setter将接受DateTime对象,并且只有DateTime对象PHP本身将确保接受的参数是DateTime对象的实例,那么您就错过了代码应该如何工作的要点。一种方法是创建一个DTO(数据传输对象(,例如CreateAuthorRequest,并创建一个符号形式类型,在该类型中您可以接受字符串/DateTime(最好是具有regex的字符串,以确保该字符串是有效的日期时间字符串(。然后在您调用$form->isValid((您可以从DTO读取数据并确保其有效。如果你仍然很难正确实现这一点,请在答案下方评论,我将提供代码示例
此外,我不建议在实体中放置那么多注释,它会很快变得混乱,更喜欢XML配置而不是注释。