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 )
So we need a more simple solution
Moderator: General Moderators
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.I have used the Rules bases Validator class approach to Forms validation for a long time and have yet to find something better
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).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.
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 != '');
}
}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
}Code: Select all
$validate->validateString("$_POST['name']", "3", "20", text, y);andThis is a cut down version that uses a Request array rather than a Request container object and only has one simple rule
But I guess I'll have to read up some more about design patterns to understand this, isn't it?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
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: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:in which the different arguments represent things like what to validate, minimal length, maxlength, kind of string, obligatory, etc etc.Code: Select all
$validate->validateString("$_POST['name']", "3", "20", text, y);
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.
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);
}
}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);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:I do have some things I do not understand:andThis is a cut down version that uses a Request array rather than a Request container object and only has one simple rule
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.matthijs wrote:But I guess I'll have to read up some more about design patterns to understand this, isn't it?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
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:quocbao wrote:I also want to use both javascript and php to validate user input![]()
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;
}
}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?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?