I am working on a PHP project which makes extensive use of the MVC design pattern. I am looking to add validation to a form and am curious as to what the right place for validation is.
Due to the way that forms are generated, validation on postback data is a lot simpler and less repetitive in view components. Is it acceptable to have the view validating response data, or should this be implemented within the controller, or even the model?
What are the benefits?
If you're validating the data on client side (i.e Javascript validation) which is absolutely not enough and not secure at all, You should implement it in View.
If you're validating data on server side, And your validation does not require application business logic (i.e you're not checking to see if the user has enough credit in his account), You should validate in the controller.
If the validation requires business logic, Implement it inside the model and call it via controller.
Postback validation is not good since it puts lots of pressure and delay, And the only advantage is to the programmer (not to be accounted).
You can use regex for most of validation, Which has the same syntax (almost) on PHP and JS.
The right place for validation is the Model.
This makes most sense because you are doing validation on the data, which is what the model represents. In terms of the CRUD updates, the model should always be used somehow.
If you are changing data from the
view, you should have validations
being checked.
If you have controllers changing
data, you should have validations
being checked.
And finally if you have having the
model itself changing data, you
should still have validations.
The only way to achieve this state is to have the validation go into the model.
Due to performance and faster response, after implementing the validations in the model, you should try to add some sort of client side(JS) to immediately notify the end user.
Validation is always about the data. Why are you validating data? So you can keep the integrity of the information your storing. Having the validations at the model level allows data to theoretically be always correct. This is always a neccesity. From there you can add extra validations in your business logic and client side to make your application more user friendly.
Validation in the model seems to be the most common approach (you end up with something like $obj->isValid()
) and this is suitable in many situations.
However, depending on your use case there may be good reasons to perform validation outside the model, either using separate validation code or in the controller, etc.:
- If much of the overall validation problem involves information not accessible to the model (for example, if an admin user can perform transformations that a regular user cannot, or certain properties cannot be changed after a certain date), then you might want to check all these constraints in the same place.
- It may also be convenient or necessary to apply very lax validation rules when constructing objects for tests. (A "shopping basket" object might ordinarily require an associated user, who in turn requires a valid email address, etc. A 100% valid shopping basket object might be inconvenient to construct in shopping basket unit tests.)
- For historical reasons, validation rules might change (e.g. enforcing a "gender" where previously none was necessary) and so you may end up with different versions of data that need to be treated differently. (Different validation rules may also apply to bulk data import.)
- If validation is very complex, you might want to provide different error messages (or none at all) depending upon what's most useful to the caller. In other situations,
true
or false
might be all that is necessary.
It may be possible to handle these different use cases via arguments to the model's isValid()
method, but this becomes increasingly unwieldy as the number of validation styles increases. (And I do think it's almost guaranteed that a single "one size fits all" isValid()
method will eventually prove insufficient for most non-trivial projects.)
Don’t get confuse with sanitizing or cleaning the posted value with validation. You should fetch the posted values and scrub them by removing any malicious elements from the values within the Controller. Then send the data to the Model to be validated for the expected values or format. By breaking those actions into two procedures reduce the risk of malicious code to get implemented. This method works well if you are using the “trust no one input” policy; knowing some programmers can become sloppy or lazy. Another positive side is preventing your Model from becoming bloated and over worked, if so, then use a model helper to do the dirty work. This approach will also help balance your application load and improve performance.