php - Validate a domain entity upon setting each property, or all at once later?

117

When validating a domain entity, is it better to validate the values as they are set, or all at once with a validator (such as in Symfony2) later on?

For example:

Option 1. Validate while being set

public function setEmail($email)
{
    if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new EntityException('The specified email address ' . $email . ' is invalid.');
    }

    $this->_email = $email;
    return $this;
}

Option 2. Validate later...

$user = new UserEntity();
$user->setEmail('[email protected]');
$validator = new Validator();
$validator->validate($user);

Option 3. Both of the above (although seems a little redundant and not worth the overhead).

I know that the first one probably makes for more airtight entities, but the second one makes for more user friendly error handling.

Also, the second option seems easier to configure and maintain...as I don't have to adjust the setters, and I can centralize my validation logic to a single class.

What it boils down to...
So basically, it sounds like Option 2 is what I WANT to do, but feel like sacrificing the airtight-ness of the entity (for example, if I forget to run the entity through the validator), might be stupid.

513

Answer

Solution:

There are doubtless going to be situations where validation is unnecessary at the application level (i.e., you know you are working with valid data at a particular point). Although there's nothing wrong with applying validation in these cases, it's certainly superfluous.

In addition, you might find yourself in a scenario where you want to perform a "mass validation" of incoming data. This would likely apply more to a service or to custom-implemented forms where you don't have e.g., Symfony's form validation framework to fall back on.

These would tend to indicate that Option 2 is the more desirable way to go, perhaps with caveat that the validator should be invoked automatically when attempting to persist the object (e.g., during the model's pre-save event; I'm not familiar with Doctrine 2 yet, but Doctrine 1.2 does have its own validation framework that can accomplish this).

Having invalid data is surely never a desirable scenario, but so long as you can be assured that invalid data are not persisted, this gives you the freedom to trust that any data you pull from the database are valid (note that I say "valid" here, not "trustworthy"!).

634

Answer

Solution:

Single Responsibility Principle

The best is to have all necessary validations in a separated layer. With that will be easier to maintain and test the validators. Also easier to validate data across your application.

Don't Repeat Yourself

You don't have to call validate() for each entity.

All you have to do is to implement the validation on your repository layer or service layer if you have one.

$user = new User();
// [...]
$user->setEmail('myinvalidemail#blah,com');
$repository->save($user);

So in your user's repository

UserRepository extends AbstractRepository {}

And the common validation for all entities:

abstract class AbstractRepository {
    public function save($entity) {
        $validator = // Get your validator based on the entity's name or something else
        $validator->validate($entity); // Throws exceptions or flag the  fields for future use

         // Now save it...
    }
}

People are also looking for solutions to the problem: php - Insert checkbox data into database, based on if it is checked or not

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.