For my framework I've written down this concept to solve the form validation problem. I want it to be as straightforward as possible for the framework user.
Every Form (=object) has one or many FormElements (=objects). Every FormElement can have 0-n FormValidators (=objects). Everything easily configured through the backend (simple drag&drop stuff).
When the Form View is rendered, it loops over all the FormElements, and for each of them it loops over all their associated FormValidators. That way it builds up all the needed JavaScript to validate the form on client side.
A FormValidator is an lightweight object which defines only these seven things:
PHP class name of the validation utility class
method name of the validation utility class, which must be called
a string for additional arguments (comma-separated values)
JavaScript "class" name of the validation utility
"method" name which must be called
a tring for additional arguments (comma-separated values)
an associated ErrorInfo object which contains an formatted error message
Every of these validation methods takes as first argument an input variable with the input data. Every of these methods just check the input if it matches some rule(s), and returns TRUE or FALSE.
When the form is submitted, an FormDataManager is created and receives:
- the Form object (so it knows from where the data came from)
- the input data (typically $_POST)
It then just iterates over all the FormElements, checks all their FormValidators, and if anything is invalid, it reloads the Form which is passed the error messages array. If everything is fine, the data is further processed (i.e. stored to db).
Are there improvements in this design? Anything I've missed?
One common validation concept which I think you have missed is validation groups. For instance, you may want to cater for one of the following scenarios:
Form field B is mandatory only if field A has any value.
Form field B is mandatory only if field A has a specific value.
Form field B is mandatory only if field A is in a specific range (numerical or dates).
Either field A OR field B needs to have a value (they cannot both be empty).
Either field A OR field B needs to have a value (they cannot both be empty or both have a value) - (XOR).
Password and confirm password fields need to be equal.
And I'm sure there are other scenarios where validation depends on the validity or optional aspect of other form elements. Also - 'mandatory' in the scenarios above may also be simply 'applicable', which would be a different situation again.
Typical (medical system) example here is: "Are you male/female?", with a follow-up of "Are you pregnant?" for females. Or AOP related questions, where you have the birthday and have a certain follow-up question only IF they are 65 years or older.
It means you need some validationgroup or validation association object that contains these dependencies in a useful and generic way.
I guess in your design it means you can also have FormValidator objects that are not directly linked to one FormElement but to a combination of FormElements and include a conditional check before triggering validation.
Sounds interesting. I think you're on the right track, especially because it sounds like you are validating both client side and server side.
One thing that you should do (and I might have missed this when reading your question) is make sure that the validation also happens on the server as well. That way your form information is still validated even if someone turns off or tinkers with the javascript.
Related
In Symfony 2.5.10, I have multiple form types, each with their own validation groups, calling various class constraints. Each type represents a particular step in a workflow. The final step iterates over all other steps, performs the necessary validation and displays any possible violations to the user.
The data behind each form type (data_class) is always the same: a doctrine entity.
Each displayed violation links to the URL/path representing the step in question, with an additional parameter which, when present, should trigger the validation. The idea is that the form should display the errors immediately, without submitting. In other words, I wish to trigger form submission programmatically (server-side, not JS!).
I've tried various different ways:
Somehow put the entity (which I have) into the request and set the method of the latter to POST, so that Form::handleRequest handles everything automatically. Problem: converting the entity object to an array, as would be returned from a real form submission. Maybe a DataTransformer? PropertyAccessor?
As 1. but call Form::submit instead. See http://symfony.com/doc/2.5/cookbook/form/direct_submit.html#calling-form-submit-manually
Validate myself (in the same way I do in the final step), giving me a ConstraintViolationList. Iterate over the list and call Form::addError for each violation. Problem: I need to add the errors to the correct child elements, not just the parent. Maybe I could do this using the propertyPath of each error, but how to go from that to child form?
Any help would be much appreciated. I've trawled stackoverflow and the web in general, but to no avail.
First way looks good. You just should check the ajax form and them just use something like
$entity = $form->getData()
to retrieve data from form (which could be array, entity, or some other stuff you have in you form).
Then just pass this entity to the twig view to form an request answer. Alongside with entity you might want to provide form errors aquired from $form->createView() FormView object.
My Symfony2 (2.4.2) application has a form, and an entity which I have set some validation constraints on some fields. One of the entity's variables is an array which should not be blank.
The form has a field which is not mapped to the entity directly. The input is a comma-delimited string; this string will be preg_split into an array and saved to the instance variable aforementioned. This operation is triggered by FormEvents::POST_SUBMIT.
However, when I submit the form, even though the input string is not empty, the form shows that the validation fails. I did a bit of debugging and found that the validation actually happens before FormEvents::POST_SUBMIT. I have tried other FormEvents but no luck.
Is there a way to trigger the event before the validation?
Note: The scenario above is shortened, it'd be too long for me to ask a question if the context is my real application.
Use DataTransformers for this sort of operation. Not form events.
The data transformer will kick in before the validation. The transformer will transform whatever the user types into whatever you expect internally. The validation will then operate on the internal data format.
http://symfony.com/doc/current/cookbook/form/data_transformers.html
Since I got into learning about MVC I have always validated my form data in my controllers which is a habit I picked up while skimming through CodeIgniters code but I have learned that its way of doing certain operations is not the best, it just gets the job done.
Should all form data be validated by the domain objects? And if so should it be done in the setters like so
public function setFirstName($firstName) {
// Check if the field was required
if(!$firstName) {
throw new InvalidArgumentException('The "First name" field is required');
}
// Check the length of the data
// Check the format
// Etc etc
}
Also, for example, if I am handling a basic user registration my User class does not have a $confirmPassword property so I would not be doing
$user->setConfirmPassword($confirmPassword);.
One way of checking if the two passwords entered are equal would be to set the $password and do something like
$user->setPassword($password);
if(!$user->matchPassword($confirmPassword)) {
throw new PasswordsNotEqualException('Some message');
}
and this would be done in the Service layer I would think?
Any advice to help me in the correct direction would be great. Thanks.
Should all form data be validated by the domain objects? And if so
should it be done in the setters like so
IMO you should only let creation of valid objects, and the best way to archieve this is to make those checks in the method that creates an object.
Assuming that the first name of an user cannot be changed, you would validate that upon the user creation. This way, you forget about the setter because you won't need it anymore.
There may be cases when you want a property to be changed, and you would need to validate them too (because that change could lead form a valid object to an invalid object, if that's the case).
One way of checking if the two passwords entered are equal would be to
set the $password and do something like...
You can handle this one the same way: have a Password object that checks both the password and confirmation upon its creation. One you have a valid Password instance, you can use it knowing that it passed all the validations you specified.
References
Those design principles (complete and valid objects from the start, etc) are from Hernan Wilkinson's "Design Principles Behind Patagonia".Be sure to check the ESUG 2010 Video and the presentation slides.
I've recently answered another question about validating properties I think you may come in handy: https://stackoverflow.com/a/14867390/146124
Cheers!
TL;DR
No, setters should not be validating the data. And nick2083 is completely wrong.
Longer version ...
According to Tim Howard's provided definition [source], the domain objects can verify the state of domain information that they contain. This basically states, that for you to actually have a domain object, said object need to be able to validate itself.
When to validate
You basically have to options:
validate in each setter
have one method to validate whole object
If the validation is a part of setter, there is one major drawback: the order of setters matters.
Example: lets say you are making an application which deals with life insurance. It is quite probable, that you will have a domain object which contains the person that is insured and the person that gets awarded the premium, when policy is triggered (the insured on dies). You would have to make sure that the recipient and the insured are not the same person. But there is no rule to govern in which order you execute the setters.
When you have two or more parameters in domain object, which have to be validated against each-other, the implementation becomes a bit fuzzy. The most feasible solution is to check when all parameters are assigned, but at that point you have already lost the benefit of in-setter validation: the execution of code has moved past the origin of invalid data.
And how would you deal with situations, where the valid state of domain object is not having a parameter A set if parameter B is large then 21 and C is already set?
Conclusion: validation in setters is only the viable solution, when you have very simple domain objects, with no tangled validation rules.
I'm working on my first CodeIgniter application and have encountered some confusion around handling post data.
More specifically, I understand the role of $this->form_validation->set_rules(), and how set_value() works to repopulate input values when the validation failed, but what I can't figure out is if $this->input->post is the same value as the set_value equivalent.
I understand that the majority of validation rules would have a boolean result, however what about ones like trim|htmlspecialchars - these also have the benefit of preparing the data for db queries.
So in my model, can I access the inputs after being processed by the Form Validation library, or should I do the additional preparation inside the model directly onto $this->input->post('variable')?
My gut tells me that I should add final processing like htmlspecialchars right before the SQL in the model, as it is really a db specific operation (I would not want & instead of & in my form inputs, but I would want & in the database).
Incidentally in my reading I did come across $this->validation->variable which would appear to have been the answer to my question in previous CI versions.
They are similar, but not exactly the same.
You would use $this->input->post('variable'); within the controller only. This variable will be validated and cleaned (if you decide to clean it with xss_clean or apply any other prepping functions).
set_value() should only be used within the Views. While this is not essential, the real value of doing this opposed to using $this->input->post is you can set a "default" value as the 2nd parameter which is automatically used if the post value is empty.
As mentioned set_value() is strictly for repopulating form inputs - nothing else. For example, set_checkbox() is going to return something like checked="checked" which is obviously not what you want to send to your model.
There's room for argument about where the input validation and prepping should be handled, but most will agree that it should be done in the controller.
You can do additional processing in the model if you wish, but generally you don't want to be accessing $_POST from the model - it makes the model less useful. Not all data is going to be coming straight from the user, so it's better to prep the data beforehand and send it as a new array/object to the model. The model should not care where the data is coming from.
Let the form validation library and controller layer process the user input (what it's intended for), and the model can process the data you send to it.
Developer
I work both frame work cakephp and codeignator. I feel best thing cakephp data validation. spouse you have 8 fields form you create validation in controller with designator. After validation all fields is empty if you fill 8 fields and by mistake 1 fields miss then after validation codeignator data validation refresh page and empty all fields.
but in cake php just opposite data validation create in model you create one time validation and use some thins when you call model then call validation exp: add,edit.
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/