构造时的原则实体验证
Doctrine entity validation at construct
我正在努力通过教义和最佳实践来提高自己。
我找到了一个很好的最佳实践介绍:https://ocramius.github.io/doctrine-best-practices/#/50
我尝试在 __construct 之后拥有一个有效的对象。
(参见 https://ocramius.github.io/doctrine-best-practices/#/52)
但是我正在使用@Assert 注释来验证我的对象。
我该如何验证?必须在 __construct 处将验证器服务注入到我的对象中?
我的对象:
class Person
{
/**
* @var int
*
* @ORM\Column(name="id", type="guid")
* @ORM\Id
* @ORM\GeneratedValue(strategy="UUID")
* @expose
*/
private $id;
/**
* @var int
*
* @ORM\Column(name="name", type="string")
* @Assert\Email()
*/
private $email;
public function __construct($email, ValidatorInterface $validator){
$this->email = $email;
$validator->validate($this); // good practice ?
}
我的最终目标是对该实体的输入验证进行单元测试。
谢谢
编辑:
根据 Yonel 的回答,我在构造函数的末尾添加了这个:
$errors = $validator->validate($this);
if(count($errors) > 0) {
$errorsString = (string) $errors;
throw new InvalidArgumentException($errorsString);
}
这是否是一种好的做法?如果不是,为什么?
谢谢!
Xero 不需要在 __constructor
中注入验证器服务(即糟糕的设计恕我直言)来验证您的对象。约束在两个可能的事件上得到验证:
使用验证器服务
要实际验证 Person
对象,请在 validator
服务上使用 validate
方法。验证器的工作很简单:读取 class 的约束 (@Assert
) 并验证对象上的数据是否满足这些约束。如果验证失败,则返回一个非空的错误列表。
例如在你的控制器中:
$errors = $this->get('validator')->validate($person);
if (count($errors) > 0) {
$errorsString = (string) $errors;
}
您要强调的原则是关于应用程序的表示层,该应用程序可以使用 可以验证用户输入的表单组件 然后此数据用于实例化实体。
在演示文稿的示例中,命名构造函数将表单作为参数,因此电子邮件地址的验证由表单完成(验证用户输入)。
具有 有效状态的对象的含义是关于具有名称、姓氏和电子邮件有效的用户类型的对象 (例如不为空)。
所以你可以有以下对象:
class User
{
private $name;
private $surname;
private $email;
private function __construct(string $name, string $surname, string $email)
{
$this->name = $name;
$this->surname = $surname;
$this->email = $email;
}
public static function create(string $name, string $surname, string $email): User
{
return new static($name, $surname, $email);
}
public function fromFormData(FormInterface $form):User
{
// The form validate user input (i.e. valid email address)
return self::create($form->get('name'), $form->get('surname'), $form->get('email'));
}
}
另一种方法可能是使用 DTO,或者您可以查看 this 关于验证 DTO 对象的有用包。
希望对您有所帮助
我正在努力通过教义和最佳实践来提高自己。 我找到了一个很好的最佳实践介绍:https://ocramius.github.io/doctrine-best-practices/#/50
我尝试在 __construct 之后拥有一个有效的对象。 (参见 https://ocramius.github.io/doctrine-best-practices/#/52) 但是我正在使用@Assert 注释来验证我的对象。
我该如何验证?必须在 __construct 处将验证器服务注入到我的对象中?
我的对象:
class Person
{
/**
* @var int
*
* @ORM\Column(name="id", type="guid")
* @ORM\Id
* @ORM\GeneratedValue(strategy="UUID")
* @expose
*/
private $id;
/**
* @var int
*
* @ORM\Column(name="name", type="string")
* @Assert\Email()
*/
private $email;
public function __construct($email, ValidatorInterface $validator){
$this->email = $email;
$validator->validate($this); // good practice ?
}
我的最终目标是对该实体的输入验证进行单元测试。
谢谢
编辑:
根据 Yonel 的回答,我在构造函数的末尾添加了这个:
$errors = $validator->validate($this);
if(count($errors) > 0) {
$errorsString = (string) $errors;
throw new InvalidArgumentException($errorsString);
}
这是否是一种好的做法?如果不是,为什么? 谢谢!
Xero 不需要在 __constructor
中注入验证器服务(即糟糕的设计恕我直言)来验证您的对象。约束在两个可能的事件上得到验证:
使用验证器服务
要实际验证 Person
对象,请在 validator
服务上使用 validate
方法。验证器的工作很简单:读取 class 的约束 (@Assert
) 并验证对象上的数据是否满足这些约束。如果验证失败,则返回一个非空的错误列表。
例如在你的控制器中:
$errors = $this->get('validator')->validate($person);
if (count($errors) > 0) {
$errorsString = (string) $errors;
}
您要强调的原则是关于应用程序的表示层,该应用程序可以使用 可以验证用户输入的表单组件 然后此数据用于实例化实体。
在演示文稿的示例中,命名构造函数将表单作为参数,因此电子邮件地址的验证由表单完成(验证用户输入)。
具有 有效状态的对象的含义是关于具有名称、姓氏和电子邮件有效的用户类型的对象 (例如不为空)。
所以你可以有以下对象:
class User
{
private $name;
private $surname;
private $email;
private function __construct(string $name, string $surname, string $email)
{
$this->name = $name;
$this->surname = $surname;
$this->email = $email;
}
public static function create(string $name, string $surname, string $email): User
{
return new static($name, $surname, $email);
}
public function fromFormData(FormInterface $form):User
{
// The form validate user input (i.e. valid email address)
return self::create($form->get('name'), $form->get('surname'), $form->get('email'));
}
}
另一种方法可能是使用 DTO,或者您可以查看 this 关于验证 DTO 对象的有用包。
希望对您有所帮助