I'm trying to improve myself with doctrine, and doing best practices. I found a good presentation of best practices : https://ocramius.github.io/doctrine-best-practices/#/50
I try to have a valid object after __construct. (see https://ocramius.github.io/doctrine-best-practices/#/52) But I'm using @Assert annotation for validating my object.
How can I do to validate ? Have to inject the validator service inside my object at __construct ?
My object :
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 ?
}
My final goal is to unit test the input validation of this entity.
Thank you
Edit :
Basing on the answer of Yonel, I added this in the end of my constructor :
$errors = $validator->validate($this);
if(count($errors) > 0) {
$errorsString = (string) $errors;
throw new InvalidArgumentException($errorsString);
}
Is it a good practices or not ? If not, why ? Thank you!
The presentation take best practice both from oop and ddd world.
The principle you are highlighting is about the presentation layer of the application that can use a form component that can validate the user input then this data is used for instantiate the Entity.
In the example of the presentation the named constructor take as argument a form, so the validation of the email address is done by the form (validating user input).
The meaning of having an object with a valid state is intended about having an Object of type User that have both name, surname ad email valid (as example not null).
So you can have the following object:
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'));
}
}
Another approach could be using DTO or you can take a look at this useful bundle about validate DTOs object.
Hope this help