Sign up ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

I am trying to re-architect a web application I developed to use the MVC pattern, but I'm not sure if validation should be handled in the model or not. For example, I'm setting up one of my models like this:

class AM_Products extends AM_Object 
    public function save( $new_data = array() ) 
        // Save code

First Question: So I'm wondering if my save method should call a validation function on $new_data or assume that the data has already been validated?

Also, if it were to offer validation, I'm thinking some of the model code to define data types would look like this:

class AM_Products extends AM_Object
    protected function init() // Called by __construct in AM_Object
        // This would match up to the database column `age`
        register_property( 'age', 'Age', array( 'type' => 'int', 'min' => 10, 'max' => 30 ) ); 

Second Question: Every child class of AM_Object would run register_property for each column in the database of that specific object. I'm not sure if this is a good way of doing it or not.

Third Question: If validation should be handled by the model, should it return an error message or an error code and have the view use the code to display an appropriate message?

share|improve this question

3 Answers 3

up vote 15 down vote accepted

First Answer: A key role of the model is to maintain integrity. However processing user input is a responsibility of a controller.

That is, the controller must translate user data (which most of the time is just strings) into something meaningful. This requires parsing (and may depend on such things as the locale, given that for example, there are different decimal operators etc.).
So the actual validation, as in "is the data well formed?", should be performed by the controller. However the verification, as in "does the data make sense?" should be performed within the model.

To clarify this with an example:
Assume your application allows you to add some entities, with a date (an issue with a dead-line for example). You might have an API, where dates might be represented as mere Unix time stamps, while when coming from a HTML page, it will be a set of different values or a string in the format of MM/DD/YYYY. You don't want this information in the model. You want each controller to individually try to figure out the date. However, when the date is then passed to the model, the model must maintain integrity. For example, it might make sense to not allow dates in the past, or dates, that are on holidays/sundays, etc.

Your controller contains input (processing) rules. Your model contains business rules. You want your business rules to always be enforced, no matter what happens. Assuming you had business rules in the controller, then you'd have to duplicate them, should you ever create a different controller.

Second Answer: The approach does make sense, however the method could be made more powerful. Instead of the last parameter being an array, it should be an instance of IContstraint which is defined as:

interface IConstraint {
     function test($value);//returns bool

And for numbers you could have something as

class NumConstraint {
    var $grain;
    var $min;
    var $max;
    function __construct($grain = 1, $min = NULL, $max = NULL) {
         if ($min === NULL) $min = INT_MIN;
         if ($max === NULL) $max = INT_MAX;
         $this->min = $min;
         $this->max = $max;
         $this->grain = $grain;
    function test($value) {
         return ($value % $this->grain == 0 && $value >= $min && $value <= $max);

Also I don't see what 'Age' is meant to represent, to be honest. Is it the actual property name? Assuming there's a convention by default, the parameter could simple go to the end of the function and be optional. If not set, it would default to the to_camel_case of the DB column name.

Thus the example call would look like:

register_property('age', new NumConstraint(1, 10, 30));

The point of using interfaces is that you can add more and more constraints as you go and they can be as complicated as you want. For a string to match a regular expression. For a date to be at least 7 days ahead. And so on.

Third Answer: Every Model entity should have a method like Result checkValue(string property, mixed value). The controller should call it prior to setting data. The Result should have all the information about whether the check failed, and in case it did, give reasons, so the controller can propagate those to the view accordingly.
If a wrong value is passed to the model, the model should simply respond by raising an exception.

share|improve this answer
Thank you for this write-up. It clarified a lot of things about MVC. – AmadeusDrZaius Dec 11 '14 at 5:21

Yes, the model should perform validation. The UI should validate the input, too.

It's clearly the responsibility of the model to determine valid values and states. Sometimes such rules change often. In that case I'd feed the model from metadata and/or decorate it.

share|improve this answer

I do not completely agree with "back2dos": My recommendation is to always use a separate form/validation layer, that the controller can use to validate input data before it's sent to the model.

From a theoretical standpoint, model validation operates on trusted data (internal system state) and should ideally be repeatable at any point in time while input validation explicitly operates once on data that comes from untrusted sources (depending on the use case and user privileges).

This separation makes it possible to build reusable models, controllers and forms that can be loosely coupled through dependency injection. Think of input validation as whitelist validation (“accept known good”) and model validation as blacklist validation (“reject known bad”). Whitelist validation is more secure while blacklist validation prevents your model layer from being overly constrained to very specific use cases.

Invalid model data should always cause an exception to be thrown (otherwise the application can continue running without noticing the mistake) while invalid input values coming from external sources are not unexpected, but rather common (unless you got users that never make mistakes).

See also:

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.