MVC Question: Should I put form validation rules in the controller or model?

PhpCodeigniter

Php Problem Overview


On one hand form validation could be seen as part of the application logic and therefore belonging in the model.

On the other hand, it deals directly with the input coming from view and handles displaying errors, etc. From that angle it makes more sense to put it into controllers.

Which one is the right approach from the MVC point of view?

P.S my form validation actually consists only of writing a list of fields, their rules, and passing it on to a form validation library, which returns true/false on whether it passed validation or not.

Example:

$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Name', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
//........
if ($this->form_validation->validate())
    // Process data
else
    $this->register_form(); //A controller action that will show a view with errors

Should this be put into a controller or model?

Php Solutions


Solution 1 - Php

Ideally, you want 3 layers of validation:

  1. View: Client side (javascript, html5 validation, etc.). This catches obvious errors and omissions before the data hits the controller, wasting the user's time and invoking an unnecessary page load if there are errors.
  2. Controller: This is your Form validation layer. Controllers usually are meant to handle input directly, and send it over to the model. It is very rare that every field in your form has a directly related column in your DB, you usually need to alter the data in some way before passing it to the model. Just because you have a field you need to validate called "confirm email", doesn't mean that your model will be dealing with a "confirm email" value. Sometimes, this will be the final validation step.
  3. Model: This is your last line of defense for validation, and possibly your only validation in the case of sending data to the model without it coming directly from a form post. There are many times when you need to send data to the DB from a controller call, or with data that is not user input. We don't want to see DB errors, we want to see errors thrown by the app itself. Models typically should not be dealing with $_POST data or user input directly, they should be receiving data from the controller. You don't want to be dealing with useless data here like the email confirmation.

Solution 2 - Php

Validation is Model's issue. Only model knows how your data should look like. You describe your data fields in model, so you should describe validation rules for this fields in the same place.

It seems to be obvious for me, but I'd gladly listen to opponents.

Solution 3 - Php

I would say the form validation code should be in the controller (not the model) in most cases.

Madmartigan put it best in his comment above "Form validation !== Data validation. Not all forms interact with a model"

Web forms are logically part of the View/Controller part of MVC, since the user interacts with them in the view.

Solution 4 - Php

Seems like everyone always says model hands down to this question, which has its merits (compared to the opposite), but I think the answer to the question is more subtle. Validation of the data itself should be performed on the model.

But there are other types of validation, such as whether the form has been submitted with unexpected fields (for security purposes, obviously) or whether a user has permission to make the operation requested. By putting these types of validation in the model, it cements the model (an abstraction of the data) to completely separate things, like how the user system works or how form submissions are evaluated for security purposes.

You can imagine changing one of those classes or systems of classes, then having a mess because you have to change all of your models, too. Whereas controllers are the mediator between the client input and the data: in that role, they are the proper validators of the examples above, and likely many others.

Solution 5 - Php

Taking in account other answers (and some research), if you have to validate data with rules like not-empty fields, email validation and stuff, the Controller shouldn't let this data pass through itself, but if you have rules like "only a user with a reputation greater than 150 can vote down an answer", you should do this in the model layer.

If you want to have business rules validation, I advise you to have an object like the Business Object Pattern, with that, in any part of the software when you want to "vote down an answer" you have your business logic preserved and centralized.

Solution 6 - Php

It is an interesting theoretical discussion, but if we focus on the point that the question was made in the context of Codeigniter(CI):

In CI you can specify a custom validation rule like this:

$this->form_validation->set_rules('email', 'Email', 'required|callback_my_validation');

In this scenario, you must define a public function called "my_validation" that must return true or false and the framework will add the error (if returned false) to a stack of errors.

So... if you put this code in the controller, you are inadvertedly exposing a public url, meaning it would by possible to call something like "http://yoursite.com/my_validation" (I don't think you intend that). The only way to protect this url would be to go into the "routes.php" file and prevent there the access to this url. This does not seem practical and seems to point us in the direction that CI developers intended us to handle validation in the model.

Solution 7 - Php

The model should validate its own data.

Say you have a Contact model, that only requires a first name and phone number. It should validate that first name and phone number are filled.

However, if this Contact model is part of a Quote, you may need a full name and email address as well.

In that case, you could either extend the Contact model (to be a QuoteContact model) and add more validations, or you could do the extra validations on the Quote model.

You should write your models so as to be reusable in other applications (even if they never will be), so they should be independent of the controller. If the validations are in the controller, then you lose those validations if you switch to say a command line version.

Solution 8 - Php

If you validate form in serverside using codeigniter then it validate in controller

You need to include the form_validation library using autoload like this

$autoload['libraries'] = array("form_validation") 
       

OR directly you load in Controller

$this->load->library('form_validation');

Then you set the validation rule to each form field

$this->form_validation->set_rules('username', 'User Name', 'required');
$this->form_validation->set_rules('useremail', 'User Email', 'required|valid_email');

If any error found after validation a form field then it catch in validate function

if ($this->form_validation->validate()) {
    //return back to form
} else {
    //successful validate all field 
}

Solution 9 - Php

There is another angle to this not covered in the other answers. It depends on what you are saying you Controller / View is! If it is Javascript that checks for validation as users type, for security reasons you should have a validation in your backend as well (this could again be in the controller of your backend or model because anyone can just push Data through Ajax without the browser.

For performance reasons, you should have a validation in your front end controller / view as well because you don't want to be hitting your database every time a user selects an invalid Birth Date or something.

So apart from the theoretical foundation of validation in M, V, and / or C you must also consider the practicality of frontend vs backend irrespective of MVC.

My personal recommendation is to not limit yourself to only one level of validation. An ill placed validation (like the Confirm Password example mentioned in the other answers) can have serious implications on the architecture.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAliView Question on Stackoverflow
Solution 1 - PhpWesley MurchView Answer on Stackoverflow
Solution 2 - PhpNemodenView Answer on Stackoverflow
Solution 3 - PhpJohnWrightView Answer on Stackoverflow
Solution 4 - PhpRyan WilliamsView Answer on Stackoverflow
Solution 5 - PhpViniciusPiresView Answer on Stackoverflow
Solution 6 - PhpLuís OsórioView Answer on Stackoverflow
Solution 7 - PhpNeil McGuiganView Answer on Stackoverflow
Solution 8 - Phpprash.patilView Answer on Stackoverflow
Solution 9 - PhpGaurav RamananView Answer on Stackoverflow