Controllers are there in MVC pattern to process user input and output. So, input validation and response preparation should be done in a controller.
For instance, I have a controller method "save" which:
looks for input data
runs a validator on the data
if inputs are valid, loads an appropriate model, sets its fields to input values, and calls its save() method
if inputs are invalid, prepares data to re-load the edit form, shows the form
All this sequence creates quite a mess of linear code. I'd like to separate it somehow. Do I move the validation part to a model? Sounds wrong? Do I create a special "library" class to handle inputs?
In Asp.Net MVC this would be better as they have implemented the "object binder" pattern. Hence, the validation and model field binding goes away and controller gets much lighter. Is there something similar for CodeIgniter?
It is not widely accepted that controllers do validation, I do them in model as per "keep your models fat, controllers thin and views dumb".
It depends on the business logic what is a valid phone number and so on, so it only makes sense for me to have it in model.
I would do exactly as you have eluded to and put as much logic into your models as possible. Controllers really should, imo, be used for initiating services and preparing data for views.
You should as much code reusable, ie validators, filters etc..
Related
I know that the CI way of doing this is to validate against the rules in the controller, but I think this is not the ultimate approach. What would you recommend me to do follow the CI way or validate incoming data in the Model, so my model will always be protecting itself against bad data. My understanding of MVC is that controller don't have to keep any program logic, all the logic is implemented in the model. I will appreciate if you can explain in detail why both approaches are good and not and which one is recommended ?
Cheers
There is no silver bullet.
Validation in the model protects you against programatic sources of invalidation. However, users do not get direct access to your models but only through controllers and ultimately through forms. Most of the time you need additional validation which is specific to a certain form or a certain controller and which is inappropriate in a model.
This argues for a layer of validation outside the model. Ideally you can create a separate validation object (maybe tied to a specific form) which is used by the controller. Occasionally you may need additional validation in the controller itself.
Validation is not binary. There are many layers of validation and different types of validation necessary in different contexts. You may need validation in both the model and the controller.
I've searched around but there doesn't seem to be a clear consensus on which one is better. Currently, all the HTML forms on the site point to a single PHP file. Each form has a hidden input specifying the action (e.g. 'user-login', 'user-logout'), and the PHP file calls methods from that.
So my question is: Should I point each form back to itself, related forms to a single file or all forms to a single file? And in terms of MVC, should processing take place in the controller or form?
Should I point each form back to itself, related forms to a single file or all forms to a single file?
You should point everything to index.php, which then delegates other components (controllers in MVC terms) to take care of the processing. The controller will then decide which view it wants to render. index.php would be in this case something we call the front controller. (note: below I am recommending ZF1 as a learning platform. ZF1 has a "front controller" class. Some people may argue that THAT one is the front controller and index.php is what they call the entry script. In my opinion, that is only the second "front" controller. Nevertheless, both opinions are controversed, so make your own opinion).
And in terms of MVC, should processing take place in the controller or form?
In terms of OOP first and foremost: the object is the only one who knows how to validate its own data (the principle of self-containment), so the form should validate itself. If it's about a model, the model should be called by either the controller, or the form - it's a matter of taste. No matter which way, the same principle applies: you feed the Model with data and call its validation method.
As you may have noticed, the Form class is a Model.
Don't let yourself fooled by the hype called MVC. Respect the OOP principles above all.
Regarding MVC: the MVC pattern says: the controller only coordonates the other components, for instance it takes the input, creates a Form instance, and calls the Form's validation method.
I advise you to use a framework to better see how all these pieces work together. The best would be zend framework 1, which has little to do with real life requirements, BUT which is a masterpiece in terms of patterns and practices.
Maybe ZF2 will change that mistake with the extra front controller.
Looking at the other answers, I feel the need to clarify some terminology used in my answer:
Model is a model. There's plenty of documentation about MVC
Form is a subclass of Model. It takes care of the validation. It may also have a method Form::__toString() which renders the HTML form in the view (the V in MVC)
view is the html file, and it's rendered under the supervision of the controller (C in MVC)
To recap, the overall execution flow would look like this:
<form action ...
entry script (a front controller)
router (it decides which Controller to forward the request to)
the Controller coordinates all the actions, calling the Model::validate() of one or many models (including Form, which is also a Model)
in the end, the Controller choses to render() a view (a html file), which could contain a call to Form::__toString(), in which case the Form is a hybrid of Model and "renderer".
Fun
Profit
That's it, basically. Different frameworks have different data/execution flow. ZF1's looks like this for instance: http://www.slideshare.net/polleywong/zend-framework-dispatch-workflow
In MVC terms your processing should take place in the controller. You shouldn't have any processing logic in your form (the view). Whether you have a different controller for each form is up to you. You could, for example, have a single controller that accepts all form submissions and performs some common processing (such as csrf detection) and then invokes your other controllers for each form. Alternatively, you could have a single controller that loads validation requirements from a database and behaves differently depending on which form has been submitted.
In MVC terms, making all form point to a single script means you've got a Front-Controller for Forms. There is one controller that deals with form requests.
Should I point each form back to itself, related forms to a single file or all forms to a single file?
That depends on your needs and the design maybe even architecture of your site.
And in terms of MVC, should processing take place in the controller or form?
Processing in MVC normally takes place within the controllers (lightly only) and the models (heavy processing). So if you're looking for an exemplary MVC design implementation you most probably will have Form Models that are used by the Controller(s).
This will ensure that you can make use of forms more flexible and you don't duplicate code for form processing within your application.
In my opinion you should use one file for each purpose. Same as mvc structure, this is a good approach for programming and it will be helpfull when your code gets really complicated.
You question closely relates to the Front Controller Pattern. In my opinion you lose nothing with pointing verything to a certain script, but win the flexibility do execute certain actions without having to repeat (and probably foget at some place) those actions.
So I would recommend to point all forms to one script.
Btw. it is the controller who handles the form processing in terms of web MVC.
Following on from my comment on Flavius' answer.....
The object encapsulating the form should be used for both presenting the form to the user and retrieving data sent back from the user. Using 2 different codesets to operate on the same dataset undermines the principle of encapsulation. Consider if your login form has a name and a password field. If you decide you want to process a sha1 hash of the password in place of the original value, you may have to modify 2 bits of code in 2 different places!
This does not mean that both instances of the form object need to be implemented within the same URL path; consider PHP's 'require' and auto_include constructs.
Where multiple input sets are multiplexed via the same URL path, this is referred to as a Front Controller pattern.
There are benefits and issues with Front Controller vs the more distributed approach.
Front Controller:
allows common processing to be implemented in one place only (e.g. authorization, logging)
moves structure of the application away from filesystem layout and into code, therefore control over application structure implemented within code
simplifies handling of bookmarks
Non Front Controller:
much easier to support
application structure evident from webserver logs
more robust - since breaking one script deos not break whole site
better performance - no need to load huge amounts of redundant code / deferred loading of processing target
There have been a couple of discussions regarding the location of user input validation:
Should validation be done in Form objects, or the model?
Where do you do your validation? model, controller or view
These discussions were quite old, so I wanted to ask the question again to see if anyone had any fresh input. If not, I apologise in advance.
If you come from the Validation in the Model camp - does Model mean OOP representation of data (i.e. Active Record/Data Mapper) as "Entity" (to borrow the DDD terminology) - in which case you would, I assume, want all Model classes to inherit common validation constraints. Or can these rules simply be part of a Service in the Model - i.e. a Validation service? For example, could you consider Zend_Form and it's validation classes part of the Model? The concept of a Domain Model does not appear to be limited to Entities, and so validation may not necessarily need to be confined to this Entities.
It seems that you would require a lot of potentially superfluous handing of values and responses back and forth between forms and "Entities" - and in some instances you may not persist the data recieved from user input, or recieve it from user input at all.
I much prefer to put validation in the model, personally. Security considerations of course are beyond the scope of what a model should be used for, but nothing says that a model is updated in exactly one place by exactly one form. By putting type validation and sanity checking outside the model, you have to validate every time you set anything on it, which leads to copy/pasted code that's difficult to update.
I use Zend_Form as part of my models - models are creating the Zend_Form objects. I go this way because Zend_Form is not about the form rendering only; backed up with Zend_Validate and Zend_Filter it is a very powerful tool (my fav from the ZF stack). Matthew Weier O'Phinney wrote a nice post about using Zend_Forms in models: http://weierophinney.net/matthew/archives/200-Using-Zend_Form-in-Your-Models.html
Data validation should be on its own, called by the controller just before committing to the model.
Haven't used PHP and haven't worked with Zend framework (have heard though), but I really like Jimmy`s blog post about validation from domain driven design perspective.
I considered many different approaches of data validation, and decided that best way of validation - it's validation before entity creation, since validation it's something which can be very dependent from context, and entity itself should not perform validation, because entity should always be in valid state.
So maybe best approach - use separate validation classes to validate data before passing it to entity constructor.
When handling user input, you should definitely handle all logic-oriented validation outside the model.
The model doesn't care about your business logic. The model doesn't care if your start date is after your end date - all the model cares about is that the date is a valid entry for that particular field in the database. It checks the data, sees a properly formatted date and moves on to the next one, because the model's entire realm of responsibility is to ensure the smooth flow of data to and from a data source.
Classes like Zend_Form are nothing more than abstractions of your view.
I've always used the model as something to more or less store and execute database queries. I have heard about the fat model, thin controller concept.
The way I setup my models right now causes a lot of junk in controllers for things like validating forms, formatting data. Does form validation, file uploading and data formatting belong in the controller or the model?
I realize this question is subjective, which should create some good discussion rather than a concrete answer.
Form Validation should definitely be part of the model. I generally represent each form as one model and pass it the sanitized post/get paramaters. The model can then take whatever action is necessary based on the input and use a property (optionally with a getter) to signal success or failure. In psuedo code you want it to look something like:
class Controller
{
function action()
{
$input = new Input();
$form = new FormModel($input);
if ($errors = $form->errors())
{
//load the appropriate view for the errors
}
else
{
//load the appropriate view for success with an optional redirect
}
}
You have two main roads to go. Thin controller/fat model or fat controller/thin model. Basicly is were you put most of the interaction. I prefer to keep at the model the major portion of the code. That way, the code is available in virtually every controller and/or lib. If the code remain at controller, it's hard (but not impossible) to use it in other controllers.
Things lije validations and other common tasks should be in a lib or helper. You can produce a set of "workers" (this is the name I give to them) to do the heavy lifting. Also, CI has a LOT of ready made libs and helpers both from the CI team and the community. Mess around the wiki to find the wealth of information available.
Hope this helps
Vx
The model is what interacts with the data (most often a database). Controllers use the models to access the data.
This is a quick question relating to Symfony, but could be a general MVC question.
I have a class in my model, for example, WebUser. This class has a property of email_address. This value must be unique to each WebUser.
Now, I've made it so all my Symfony forms validate that the email_address is unique for the given WebUser, however I'm wondering if I should add this validation to the model as well?
But this also got me thinking, should you actually validate every set() method in the model? It seems a wise enough decision to make sure no erroneous data ends up in the database, however most (if not all) data has to go through the controllers, which validate as well. So to me it seems I'm running the same validation twice and it just seems pointless?
What are your thoughts on this? I'm still leaning towards validation in the model as that makes the most sense as it dictates the business logic.
If you should validate in the model, how do you throw an appropriate set() error in Symfony that is handled correctly by the form framework?
Thanks.
I disagree with "Validation should be part of domain logic, not front-end logic".
Validation is a complex functional part of your application and must be context aware. ie. you have to know is the user is logged in, what kind of credentials she has, the status of the request/form and so on. Models instead must be context agnostic (to work in any environment not only http request but also cli etc.) so they don't know about the user, the state and the http request. This is a strong requirement for the testability of your model classes.
For the summentioned reason functional validation must belong to the form which knows the application state (ie. session). symfony helps a lot with the sfValidator* classes which belongs to the form component indeed. That's the reason why forms are tested with functional testing.
Data validation should be in the model instead (ie. check if the value is an integer or a string, check if it's null and so on). This is easily accomplished with the Doctrine in-schema validation rules.
I can't speak specifically to Symfony, but I know that I purposely shun Zend Framework's form validation, and instead validate on my models (Zend Framework does not provide its own Model component, so it has no actual opinion on the matter).
There's nothing wrong with validating on the form, but I think you should also be validating on the model. Validating on the form might be useful for quick and easy input checking, especially if the processing logic is complex - you won't waste time working with data that's obviously bad.
Reasons I think model validation is best:
There's a chance a model will alter the data after it passes through the form and before it goes into the DB
Validation should be part of domain logic, not front-end logic (I realize Symfony seems to disagree).
Validation state travels with the model object, instead of the form object.
If you're not totally sold validating only in the model, a combination of the two sounds like a good solution.
EDIT: At the end of the day, it might make the most sense to just go with your framework on this. If Symfony seems most opinionated toward validation in the controller, and doesn't provide an easy path for validation in the model, just go with what they want you to do (or the direction in which the Symfony community leans). Fighting your framework is never fun.
I can't help out with the symfony part but most MVC-Frameworks do validation in the model, since this is the only place inside a MVC environment where validation should be.
This goes for the validation of the model's attributes of course.
I Think You Should User MVC Validator Tool Ket Insted of using others rely on modelstate its easyer and also testable and its based on formcollected not to the model that give you free run way
Regards MArwan HAfez