Page 1 of 4
Advanced Form Validation
Posted: Wed Feb 15, 2006 9:23 pm
by quocbao
i am thinking about a way to make form validation easier .
i know there's a good ( very good ) class about form validation on PHPClasses (
http://www.phpclasses.org/browse/package/1.html)
But using it's very complicated ( for designer )

, and it's almost impossible to seperate between designer and programmer ( i'm working with a group )
So we need a more simple solution

, anyone has an idea ?
Posted: Wed Feb 15, 2006 9:35 pm
by Ambush Commander
Well, I'd say this is one of those things you'd go build yourself.
Posted: Thu Feb 16, 2006 12:07 am
by Christopher
I have used the Rules bases Validator class approach to Forms validation for a long time and have yet to find something better. Those classes (along with Filter/Filterchain classes) are the building blocks of a Form Controller. Are you looking for a pre-written solution, or as Ambush Commander recommends -- building something yourself?
Posted: Thu Feb 16, 2006 1:19 am
by matthijs
http://www.phppatterns.com/docs/design/strategy_pattern might be worthwile to take a look at.
I have used the Rules bases Validator class approach to Forms validation for a long time and have yet to find something better
Arborint, do you have any good resources about that or a short explanation? I'm working on my own validation class based on the strategy pattern mentioned above, but am interested in what else is possible.
Posted: Thu Feb 16, 2006 3:49 am
by Christopher
matthijs wrote:Arborint, do you have any good resources about that or a short explanation? I'm working on my own validation class based on the strategy pattern mentioned above, but am interested in what else is possible.
That article is the long version of the code that I use. It is an interesting study in the change that has happened in the last few years from using inheritence (like the article uses) to composition (like the code below).
The interesting thing about the Validator is the recognition that you are looking for error messages because that's what you want to display. If there are no error messages you are done. But it is the pluggable rules that makes the thing so flexible. Fabulous polymorphism at work.
Here is a Rule based version:
Code: Select all
class Validator {
var $chain = array();
var $errorMsg = array();
function addRule(&$rule) {
if (is_array($rule)) {
$this->chain = array_merge($this->chain, $rule);
} else {
$this->chain[] = $rule;
}
}
function validate ($request) {
$this->errorMsg = array();
foreach ($this->chain as $rule) {
if (! $rule->isValid($request)) {
$this->errorMsg[] = $rule->getErrorMsg();
}
}
return $this->isValid();
}
function isValid() {
return empty($this->errorMsg);
}
function getErrorMsg() {
return $this->errorMsg;
}
} // end class Validator
class Rule {
var $field;
var $errorMsg;
function getErrorMsg() {
return $this->errorMsg;
}
}
class RuleNotNull extends Rule {
function RuleNotNull($field, $errorMsg) {
$this->field = $field;
$this->errorMsg = $errorMsg;
}
function isValid($request) {
$value = $equest[$this->field];
return ($value != '');
}
}
And is used like this:
Code: Select all
$validator = new Validator();
$validator->addRule(new RuleNotNull('username', 'Username required'));
$validator->addRule(new RuleNotNull('password', 'Password required'));
$validator->validate($_POST);
if ($validator->isValid()) {
// form is valid
header('Location: form_done.php');
} else {
// get error messages
$errormsg = 'Errors: ' . implode(', ', $validator->getErrorMsg());
// show form and error message
}
This is a cut down version that uses a Request array rather than a Request container object and only has one simple rule. The power is that you can create as many different rules as you want and add them in any combination. Each form field might have several rules. So for example if you also want to make sure that the Username was at least 3 characters long and the Password was at least 7 characters long, you would just add more rules for with those keys. You would need to build a RuleStrLength class that extends Rule for that.
This Validator runs after the FilterChain. I usually create a Parameter class to hold the filters, rules, and other data about each form field that the form controller then uses.
Posted: Thu Feb 16, 2006 4:59 am
by matthijs
Christopher, thanks a lot for your explanation. Although the details are a bit difficult to me, I understand the overall view.
Looks like a flexible approach to me. At first sight it would look a bit cumbersome, to write a rule for every Rule for every variable-to-validate. But at the same time that gives the approach it's flexibility, isn't it?
In a lot of validation classes the usage is something like:
Code: Select all
$validate->validateString("$_POST['name']", "3", "20", text, y);
in which the different arguments represent things like what to validate, minimal length, maxlength, kind of string, obligatory, etc etc.
But thinking about it, this approach is less flexible because the amount and kind of arguments are hardcoded in the class. When a somewhat different set of validation rules is needed in a certain situation one has to rewrite the code in the class. With your appraoch you have a set of classes, and you can call all the Rules you need for the specific validation of a variable.
I do have some things I do not understand:
This is a cut down version that uses a Request array rather than a Request container object and only has one simple rule
and
This Validator runs after the FilterChain. I usually create a Parameter class to hold the filters, rules, and other data about each form field that the form controller then uses
But I guess I'll have to read up some more about design patterns to understand this, isn't it?
Posted: Thu Feb 16, 2006 11:26 am
by Christopher
matthijs wrote:Christopher, thanks a lot for your explanation. Although the details are a bit difficult to me, I understand the overall view.
Looks like a flexible approach to me. At first sight it would look a bit cumbersome, to write a rule for every Rule for every variable-to-validate. But at the same time that gives the approach it's flexibility, isn't it?
In a lot of validation classes the usage is something like:
Code: Select all
$validate->validateString("$_POST['name']", "3", "20", text, y);
in which the different arguments represent things like what to validate, minimal length, maxlength, kind of string, obligatory, etc etc.
But thinking about it, this approach is less flexible because the amount and kind of arguments are hardcoded in the class. When a somewhat different set of validation rules is needed in a certain situation one has to rewrite the code in the class. With your appraoch you have a set of classes, and you can call all the Rules you need for the specific validation of a variable.
You don't need to write a rule for every variable -- once you get a set of standard ones the you just reuse them. For checking length you would create a rule like this:
Code: Select all
class RuleLength extends Rule {
var $min;
var $max;
function RuleLength($field, $min, $max, $errorMsg) {
$this->field= $field;
$this->min= $min;
$this->max= $max;
$this->errorMsg = $errorMsg;
}
function isValid($request) {
$value = strlen($request[$this->field]);
return ($this->min <= $value && $value <= $this->max);
}
}
So to extend the example above you could do:
Code: Select all
$validator = new Validator();
$validator->addRule(new RuleNotNull('username', 'Username required'));
$validator->addRule(new RuleLength('username', 3, 30, 'Username must be 3 to 20 characters long'));
$validator->validate($_POST);
Now the will get both error messages if they type nothing, but only the length error if the type 1, 2 or more than 20 characters. And you can keep reusing your pool of Rule classes on other fields, but you are free to write an occasional custom one as well.
matthijs wrote:I do have some things I do not understand:
This is a cut down version that uses a Request array rather than a Request container object and only has one simple rule
and
I think it is pretty common to use a standard Container type object to encaptsulate data that is like an associative array, but needs some more logic -- like the Request. It usually has get(), set() and has() methods. But Containers are separate and bigger subject.
matthijs wrote:
This Validator runs after the FilterChain. I usually create a Parameter class to hold the filters, rules, and other data about each form field that the form controller then uses
But I guess I'll have to read up some more about design patterns to understand this, isn't it?
Yeah ... the idea is to build up larger structures, like a Form Controller, from simpler, testable classes like these. If you want more specifics I could show examples of some of these classes.
Posted: Thu Feb 16, 2006 12:54 pm
by matthijs
Thanks again for your answer Christopher. You RuleLength example makes a lot of sense.
I'll definately go and try to extend this. I know how to write the basic validation rules, but to see it implemented in a structure like this is great. If you find the time and feel like it: I would certainly be interested in more examples.
Posted: Thu Feb 16, 2006 2:47 pm
by Christopher
I sent you a link to some example code. If you think it is interesting or useful I can post it here.
If you want more examples, just be specific and I can provide them.
Posted: Thu Feb 16, 2006 2:53 pm
by matthijs
Thanks, I pm'd you as well. If I'm having some trouble somewere I'll let you know.
Posted: Sat Feb 18, 2006 12:10 am
by quocbao
Thanks all for replying
I learn from you a lot
Now , new approach
I also want to use both javascript and php to validate user input
Do you have an other solution too ?
Or there is some pre-made package ? ( yes ,
http://www.phpclasses.org/browse/package/1.html , but again , i don't want to use this class )
Thanks all for helping me

Posted: Sat Feb 18, 2006 1:15 am
by matthijs
Adding client side validation is not a bad idea. There are many examples and scripts out there. However, remember to always start with a solid serverside validation. Javascript can always be disabled. Sometimes on purpose, other times someone accessing your site has no other choice. This is also important for the accessibility of your forms/applications.
So, my advice is to take two terms into account: progressive enhancement and gracefull degradation. If you want to read more about this:
If you would like to see some examples of javascript form validation:
An approach I really would like to take myself is combine both sides in some way. Because building and maintaining both serverside and clientside validation routines is cumbersome. I think 2 approaches are possible here: first is the idea to let the PHP output the js, depending on which form fields and validation rules are needed. So you only have to write the php rules, and the class/package takes care of everything.
The other possibility is one that Chris Campbell mentions in his
article: using hidden form fields which tell the server what type of validation to perform. That way, you don't have to write the client side validation routines seperately. Only include a common js validation class in the head of the document, and add the hidden input fields to the form. (which can easily be outputted dynamicly by a php script of course). If js is disabled the form is posted normally and server side validation takes place. If js is enabled, the js performs the client side validation first.
Posted: Sat Feb 18, 2006 1:58 am
by Christopher
quocbao wrote:I also want to use both javascript and php to validate user input
If you look at the Validator code above, it should be posible to write a mirror version in Javascript and the generate a CheckFrom() javascript function that would run in the form's onSubmit. Something like this pseudocode:
Code: Select all
function CheckForm(form) {
validator = new Validator();
// have PHP generate these lines
validator.addRule(new RuleNotNull('username', 'Username required'));
validator.addRule(new RuleNotNull('password', 'Password required'));
validator.validate(form);
if (validator.isValid()) {
return true;
} else {
alert('Errors: ' + validator.getErrorMsg());
return false;
}
}
The next step might be to break this down into a field by field validation.
Posted: Sat Feb 18, 2006 9:02 am
by John Cartwright
I don't know about the strategy pattern, having a class for every field that requires validation seems kind of redundant doesn't it?
Posted: Sat Feb 18, 2006 1:06 pm
by Christopher
Jcart wrote:I don't know about the strategy pattern, having a class for every field that requires validation seems kind of redundant doesn't it?
Which part is reduntant? Do you mean a "class" for every field or an "object" for every field? Are you talking about the PHP side or the Javascipt side?
The thing about "fields" for me is that they potenially need a bunch of stuff for them. For a form each data field needs a one or more filters, one or more validators, plus error messages, and potentially one or more callbacks that run on some state change (load/submit/accepted). That's just the data fields. If you think about a general architecture -- a parameter could be an Event that triggers an action. The point of a controller is to create a reusable system rather than custom coding every form. And for me encapsulating all the stuff for each potential parameter makes sense. The question is how to do it.