55

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?

yegor256
  • 102,010
  • 123
  • 446
  • 597
Lea Hayes
  • 62,536
  • 16
  • 62
  • 111

4 Answers4

113

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.

uriDium
  • 13,110
  • 20
  • 78
  • 138
Mike Lewis
  • 63,433
  • 20
  • 141
  • 111
  • 4
    this is what Yii does, and it works well. They also have "validation scenarios" so you can have different validation rules for different scenarios, such as create vs update – Neil McGuigan Feb 13 '12 at 21:45
  • If there is no difference between 'Application Logic'/'Use Story' and 'Domain Model', then putting validation in the Model looks practical to me. Otherwise, AbiusX's suggestion to put in Application Controller makes more sense. The issue is 'Application Controller' and 'GUI Controller' are different concepts. In short, the architectural decisions should determine the answer of this question. – Salman Virk Mar 08 '13 at 22:06
  • Couldn't agree more with this answer. This design aspect is a subset of the anemic vs. rich domain model discussion. And this particular example is probably one of the best to point out why anemic domain models directly violate DRY, *in a practical way* (and not only theoretically, as anemic advocates often point out) – edsioufi Sep 02 '13 at 19:15
37

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.

AbiusX
  • 2,379
  • 20
  • 26
  • 20
    I was taught to make controllers light as possible. Seems to me that validation IS part of the business logic... – dqhendricks Mar 14 '11 at 23:54
  • Thanks for the responses, they are much appreciated.There are various kinds of forms, but as an example, a member sign up form where the various inputs are validated server-side to ensure both correctness and a unique username. Invalid inputs are to be highlighted with a CSS class. – Lea Hayes Mar 15 '11 at 00:11
  • 1
    As in your example, duplicate usernames are part of application logic. But invalid characters in username could be checked at controller. – AbiusX Mar 15 '11 at 00:16
  • 2
    controllers should be light, but since validation is mandatory, it can't be skipped. Lightening controllers means not putting any logic or view in it. – AbiusX Mar 15 '11 at 00:16
  • Regex is only valuable if you first canonicalize input data, and escape for the apprpriate contexts that the data will be used in the view. (i.e., url/javascript escaping/encoding.) In most people's usage, regex isn't good enough. – avgvstvs Apr 23 '12 at 11:33
  • 5
    Controllers in MVC are part of presentation layer. They should not have any clue about how to perform data validation, that is a responsibility of model layer. – tereško Mar 01 '13 at 14:21
  • 2
    Its not like that. You mean that the UI should not be able to tell the user if they have typed a name instead of a number? It has nothing to do with the business logic of the application. It's more of a presentation matter. An Email input is a presentation matter, not a business logic matter (can be re-checked there too) – AbiusX Mar 16 '13 at 11:47
  • If you use a relation database. create contains in the database, which map the core business logic. – cSteusloff Sep 30 '17 at 17:21
2

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.

Carl Barrett
  • 209
  • 5
  • 16
1

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.)

mjs
  • 63,493
  • 27
  • 91
  • 122
  • It has been a while since I posted this question, but I have learnt from experience that it is easier to maintain the model by splitting it into two separate parts. The business model layer should apply all "business" rules like enforcing "gender" where it was previously not required. The business model can be altered to require "gender" on all new applications/updates/etc. The service model layer does not care about "business" rules but instead must validate data integrity, etc. Thus the service layer and the business layer can be tested independently. I write about this in my blog... – Lea Hayes Apr 13 '12 at 22:20
  • http://leahayes.wordpress.com/2011/04/21/business-process-and-data-with-mvc-model-view-controller/ – Lea Hayes Apr 13 '12 at 22:21