Where should validation take place?

亡梦爱人 提交于 2019-12-01 10:36:27

NOTE: Controller is not responsible for "transporting data". Controller's responsibility is altering model's (and in special cases - current view instance's) state.

There is actually third approach: have a separate isValid() method for the domain object (you call them "entities"). The setter validation becomes messy, when you have validation rules across multiple data entries.

Example: validation of repeated password for user registration form.

Having validation in setter for this will turn out quite messy. Especially if you opt to use exceptions for each failing validation.

Also, instead of data access objects I would recommend for you to use data mappers. The code would basically look something like this:

$post = new Model\Domain\Post;
$mapper = new Model\Mappers\Post($pdo);

$post->setId(42);
$mapper->fetch($post);

$post->setTitle($title);
if ($post->isValid()) {
    $mapper->store($post);
}

This approach also lets you externalize the validation by injecting some kind of Validator instance in the Model\Domain\Post instance through constructor, if you want to reuse some validation rules.

Though, when making a larger app, you will probably notice, that there are very few repeated checks, which go beyond existing php filters.

NOTE: please don't use static classes. This forces you to use procedural paradigm, where it's not needed.

Another thing that you have to pay attention to is: what kind of validation are you doing ?

Business rules should be validated in domain objects, but data integrity checks (like: "is this email address unique") are part of persistence logic. And persistence logic should (according to SRP be handled by a separate instance. In the given example that part was managed by data mapper.

I think you should have two layers of validation, your "model" validation which validates invariant conditions which apply globally to the data model. For example, "name" is required due to that being a not-null field in the database. In this instance approach 2 is appropriate.

The other layer of validation is "form" validation, and that would go in your form model, this tests for conditions which are specific to the form. Say for example you have an is_admin field on your user model, it might be valid to set this in the admin panel update user form, but invalid on the users "change password" form. This approach is probably closer to the first.

With regard to implementing it, I probably wouldn't validate it in the setter unless you want to have a test around every single "set" or you're happy to set and save only the fields which are valid. Usually you'd reject the entire update if one of the fields is invalid, so it would make more sense to have an isValid() function, which could be called automatically before saving or to test whether it's valid without saving.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!