Pregunta

I have question about OOP strategy of validating values in entity. Lets say I have entity like this:

/*
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="My\PageBundle\Entity\PageRepository")
 */
class File {
    /*
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /*
     * @ORM\Column(name="type", type="string")
     */
    private $type;

    /*
     * @ORM\ManyToOne(targetEntity="File")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     */
    private $parent;
}

Now I want to only entities type "parent" could be parents. I can do it in 2 ways.

  1. Using Symfony Callback validation:

    if ($this->getParent() != null && $this->getParent()->getType() != 'group') $context->addViolationAt('parent', 'Invalid parent.', array(), null);

which is quite obvious, but works only when I call validator, or

  1. put this logic in setter like it's proposed in Symfony book

    You should check generated entities and adjust getter/setter logic to your own needs

for example:

setParent(File $parent) {
    if ($parent->getType() != 'group')
        throw new \Exception('Invalid parent');
    $this->parent = $parent;
}

Which approach is better? Using Validation Constraints created specifically for this purpose or getters and setters? If using Validation - should I always use default getters and setters or are they any fancy (and useful) things I can do inside them (any examples)?

¿Fue útil?

Solución

I would use Symfony Callback validation, first off because it is a dedicated construct for validating entities and because your example is closer to the design philosophy of the component intended for callback validation.

While it is true that PHP OOP books encourage you to not only use getters and setters for retrieving property values, I've always used them to ensure default values and constraints on fields (i.e. I have an $id property, which is of type int, and I want to make sure to cast the value of the $id to int when setting it, even if somebody mistakenly sent in a string/whatever).

Beyond that, I also think it's weird to have a try/catch block for a setter, especially when I know that I'm sending in the proper argument type.

UPDATE: Just noticed the final part of your question. I use my Symfony getters and setters basically just for retrieving/storing values. I tend to set default values for things in constructors. I've seen some code over the years where the getters and setters do some pretty wild things, which really didn't belong within the scope of an Entity, but closer to a Service or Repository.

I think of Entities as the constructs allowing me to map the database table to a PHP class - they don't need to be smart, special, or do anything outside that scope.

I prefer keeping them simple and using the rest of the architecture to compliment the possible operations. Is it something that offers some general functionality and that can be isolated independently? Make a Service for that. Is it something to do with manipulating entities, retrieving certain info or handling them in a specific way? Make a Repository for that.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top