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?
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.
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.
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.
Related
In input of my application I have the following data: airplane_id, airport_id and passenger(s) details.
I need to make sure that selected airplane_id could reach airport_id. It might be done only with help a SQL query, but this checking is still a validation process, isn't it?
Validation should happen before I will save passenger(s) details.
In my application model, it is the ActiveRecord pattern object which represent a table. I would rather make Validator as a separated layer than to build it into the Model layer. But in this case I have an extra issue: usually Validators are general (their rules might be applied to any set of data). For instance is this data email? or IP? or date? etc.... but never mind what the data is.
In my case, the mentioned rule won't be common at all; it will definitely be a specific rule, which can't be used by any other input data. So my question is: Is this checking still part of the validation process?
And if yes, will Validator violate the S principle from the set of SOLID?
It is validation and you should use a separate validation layer (single responsibility for input validation). Input validation isn't just data type checking, it can be much more complex. Model validation might still be needed though.
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: https://lastzero.net/2015/11/form-validation-vs-model-validation/
Yes, these checks are validation.
Speaking from experience with a MVC pattern framework(Yii/2), I would say that you could make an abstract validator class and from there extend it into your concrete validators and call those validators from the model class. This will need a Model->validate() call, but having separate classes that actually check the data will not violate the S in SOLID, while Model->validate() will just loop through the validatos validate methods and store the error messages in an array.
I am trying to decide between 2 patterns regarding data validation:
I try to follow the nominal workflow and catch exceptions thrown by my models and services: unique/foreign constraint violation, empty fields, invalid arguments, etc... (!! I catch only exceptions that I know I should)
pros: Very few code to write in my Controllers and Services: I just have to handle exceptions and transcribe them to a user-understandable message. Code very simple and readable.
cons: I need to write specific exceptions, which can be a lot of different exceptions sometimes. I also need to catch and parse generic PDO/Doctrine exceptions for database exceptions (constraint violations, etc...) to translate them into exceptions that are meaningfull (eg: DuplicateEntryException). I also can't bypass some validation: let's say an object of my model is marked as locked: trying to delete it will raise an exception. However I may want to force its deletion (with a confirmation popup for example). I won't be able to bypass the exception here.
I test and pre-validate everything explicitly with code and DB queries. For example, i'll test that something is not null and is an integer before setting it as an attribute in my model. Or I'll make a DB query to check that I am not going to create a duplicate entry.
pros: no need to write specific exceptions, because I prevalidate everything so I shouldn't be doing a lot of try/catch anyway. Also I can bypass some validation if I want to.
cons: Lots of tests and validation to write in the controllers, services and models. I will be performing more queries (the validation part). The DB already does the validation for foreign keys, unique constraints, not null columns... I shouldn't ignore that and recode it myself. Also this leads to very boring code!
I would rather use one pattern or the other, not a mix, in order to keep things as simple as possible.
The first solution seems to me like the best, but I'm afraid it might be some kind of anti-pattern? or maybe behind its theoretical simplicity it is hiding situations very hard to handle?
I would suggest that data validation should happen at the perimeter of an application. That is to say, that any data coming in should be checked to make sure it meets your expectations. Once allowed into the application, it's no longer validated, but it is always escaped according to context (DB, email, etc.) This allows you to keep all of the validation together and avoids the potential duplication of validation work (it's easy to come up with examples where data could validated twice by two models that both use it.) Joe Armstrong promotes this approach in his book on Erlang, and the software he's written for telcom stations runs for years without restarting, so it does seem to work well :)
Additionally, model expectations don't always perfectly line up with the expectations established by a particular interface (maybe the form is only showing a subset of the potential options, or maybe the interface had a dropdown of US states and the model stores states from many different countries, etc.) Sometimes complex interfaces can integrate several different model objects in a manner that enhances the user experience. While nice for the user, the interaction of these models using the exception approach can be very difficult to handle because some of the inputs may be hybrid inputs that neither model alone can validate. You always want to ensure validation matches the expectations of the UI first and foremost, and the second approach allows you to do this in even the most complex interfaces.
Also, exception handling is relatively expensive in terms of cycles. Validation issues can be quite frequent, and I'd try and avoid such an expensive operation for handling issues than have the potential of being quite frequent.
Last, some validation isn't really necessary for the model, but it's there to prevent attacks. While you can add this to the model, the added functionality can quickly muddy the model code.
So, of these two approaches, I would suggest the second approach because:
You can craft a clear perimeter to your app.
All of the validation is in one place and can be shared.
There's no duplication of validation if two or more models make use of the same input.
The models can focus on what they're good at: mapping knowledge of abstract entities to application state.
Even the most complex UI's can be appropriately validated.
Preemption likely will be more efficient.
Security-focused validation tasks that don't really belong in any model can be cleanly added to the app.
I have been using php for awhile but am new to OO php. As an exercise for myself I am building a small MVC framework.
I realize there is probably not a definitive answer for this, but I am wondering: Where does the input filter / validation code belong?
Should it be a part of the controller, where the request is parsed?
Or is it more appropriate to have filter / validation code in the domain model, so that each domain object is responsible for validating its own info.
Any advice would be much appreciated.
Controller is not responsible for validation in any way, shape or form. Controller is the part in presentation layer which is responsible for reacting on users input. Not questioning it.
The validation is mostly the responsibility of domain objects, which are where most of domain business logic ends up within the model layer. Some validation is what one would call "data integrity checks" (like making sure that username is unique). Those constraints are enforced by DB structure (like with UNIQUE constraint in given example or NOT NULL in some others). When you are saving the domain object, using data mapper (or some other storage pattern), it might raise some exceptions. Those exceptions too then might be used to set an error state on a particular domain object.
If you have a form, it will be tied to one or more domain objects, which, when the form is posted, validates it. The current view then requests information from the model layer and, if there has been an error state set, displays the appropriate warnings.
Controllers would typically handle request data (GET / POST) and detect invalid form submissions, CSRF, missing fields, etc. for which the model should not be concerned about. This is the most likely place where you would write the bulk of mostly your filtering code; validation should only go as far as sanity checks for early failure (e.g. don't bother to send an email address to the model if it's not a valid email address).
Your domain objects may also provide validation hooks (even filtering), which would reduce the controller's responsibility, but in most cases I personally find it easier to work with a contract based model (the model assumes you're passing legit values) because it's easier to directly translate validation issues to specific form fields.
The model itself may do validation as well, albeit different from aforementioned input filtering (and content type validation); for instance, it might check whether an email exists in the database rather than making sure it's a valid email address.
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
This question is mainly geared towards Zend in PHP, although it certainly applies to other languages and frameworks, so I welcome everyone's opinion.
I've only recently been using the Zend framework, and while it's not perfect, I have had a pretty good time with it. One thing that drives me crazy, however, is that most of the examples I see of people using Zend do the validation in special form objects, rather than in the model. I think this is bad practice because data can enter into the system in other ways beyond form input, which means that either validators have to be bent and twisted to validate other input, or validation must be done in a second place, and logic duplicated.
I've found some other posts and blogs out there with people who feel the same way I do, but the developers of Zend made this choice for a reason, and other people seem to use it without issue, so I wanted to get some feedback from the community here.
As I said, this mainly applies to Zend, although I think it's important to look at the issue as a whole, rather than working within the confines of the Zend framework, since Zend was designed so that you could use as much, or as little, as you wished.
This is a non-zend specfic answer, however I believe that the model should be responsible for the validity of its own data. If this is the case then the validation belongs in the model, however this may not always be achievable and it may be necessary to perform validation in the view, however I think this should be in addition to the validation performed in the model not a replacement for it.
The problem with only having validation in the view is that at some point you will probably want another view on your data. Your site may become popular and customers are asking for XML based APIs to generate their own views. Do you then rely on the customer to validate the data?
Even if you do not have to provide APIs some customers may want customized views that are sufficiently different to warrant a completely different version of the page, again you now have validation in the views duplicated.
I think the ideal scenario is to have your model do the validation but to make the results of the validation available for the view to read and render the page again with the validation results displayed.
I think it is perfectly reasonable to have the view doing validation if you want to instantly display validation data back to the user etc but the final decision on data validity should rest with the model.
It's important to remember that data validation which is relevant to an application isn't always the same thing as data validation that's relevant to a database schema.
Consider a simple registration form where a user creates an account with a username and password. You perform validation on the password because you want it to be X number of characters in length and contain a good mix of character types (or whatever).
But none of this is relevant to validate the data for database insertion, because you aren't going to store plain-text passwords - you're going to store a hash of them in some way (md5, md5 + salt, whatever). Instead you might make sure that you have a 32 character hexadecimal string so that it is very likely to be a properly created MD5 hash.
This password example isn't the only scenario, just a good one for explanation here in this topic.
So what's the answer? I don't think there's any one-solution-fits-all. Sometimes you will want (need?) to validate the data twice. Sometimes you'll do it once an only in the Model. Just match it as best as possible to your application's needs.
Perhaps you should have a look at Using Zend_Form in Your Models by Matthew Weier O'Phinney - one of the lead-developers of the Zend Framework - for his view on exactly this question.
Well, the validation can be done at many different levels and usually none of them is "the best". Of course, the model can be populated with invalid data that do not come from the form, but we can also create forms whose data do not go to any model.
Moreover, the direct validation in models is unsually not integrated with our form rendering system, which causes problems if we want to show the error messages and re-populate the form with the user-entered data then.
Both of the solutions have their own pros and cons. It would be perfect to have a system that ensures us that the validation finally must be done at some level. If the form does not validate some data, then the model does and vice versa. Unfortunately, I haven't heard of such library, but I must note that the validators in the frameworks unsually are source-independent. You can pass the POST data to them, but the same can be done with the information retreived from a properly parsed CSV, MYSQL databases, etc.
I am not aware of Zend. But.
Your model have to receive valid data. Model and it's methods shouldn't check data again and again. Of course there are should be functions that do actual validation and they should be called from the gui validation or from the other data input place.
The best you can do on your model side is call "Assertions" on all the data to be sure on the development time that validation have been taken its place.
The lower level of the code (UI, model, utils) the less validation and check code should be there. As then there is a big chance that the same validation will be called more then one.
How about putting esthetical validation in the form, and business rules validation in the model.
Take a registration form for example.
The form would assure that the email field is trimmed and contains a valid email, that the password/confirm password field are identical and that the user checked the I Agree to terms checkbox.
The registration model would make sure that the email hasn't been taken yet in the table, would salt and hash the password.
It's how I split the two usually.
User input should be validated when it is being inputted because it is specific to the form of entry (ie, do some form validation - make sure text boxes that should have numbers are numbers).
Business logic should probably be validated on the model because it is model specific (ie. make sure they have't already reserved that same room or something like that).
The problem with validating it at the model level is that the model might be used in different ways. Correct input for one scenario may not be correct input for another.
The other issue is that you usually want some context sensitive validation, such as displaying a red box around the form control that has the bad input.
The model or database might do some extra validation to make sure the user code isn't doing something completely wrong (constraints, etc).
Peter Bailey's password example is excellent. A user model can only validate, if a password was set (because it's not stored as plain text but as a hash) while input validation can ensure, that the original plain text password corresponds to the security requirements (number of characters,...). Therefore you need both: Model validation and form/input validation, ideally as separate, reusable component and not directly in bloated controller actions.
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: https://lastzero.net/2015/11/form-validation-vs-model-validation/