replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Validator refactored to be OO
Based on my previous post I completely re-factored my code to make it object oriented.
Anything I could improve when it comes to:
- Object oriented code;
- Efficiency;
- Readability.
Any other suggestions are also welcome!
Validator class:
class Validator
{
private $rules = [];
private $errors = [];
public function getErrors($rulename = null)
{
if ($rulename) {
return isset($this->errors[$rulename]) ? $this->errors[$rulename] : null;
}
return $this->errors;
}
# rules will be checked against in same order as specified
public function setRule($name, Array $rules)
{
if (!array_key_exists($name, $this->rules)) {
foreach ($rules as $rule) {
if (!$rule instanceof IRule) {
throw new Exception('Array must only contain instances of IRule.');
}
}
$this->rules[$name] = $rules;
} else {
throw new Exception(sprintf('Rule %s already exists.', $name));
}
}
public function validate($rulename, $input)
{
foreach ($this->rules[$rulename] as $rule) {
try {
$rule->check($input);
} catch (Exception $e) {
$this->errors[$rulename][] = $e->getMessage();
}
}
if (isset($this->errors[$rulename])) {
return false;
}
return true;
}
}
One of the rule classes:
class Between implements IRule
{
private $errMsg = 'Must be between %s and %s.';
private $inclusive;
private $max;
private $min;
public function __construct($min, $max, $inclusive = true, $errMsg = null)
{
$this->min = $min;
$this->max = $max;
$this->inclusive = $inclusive;
if ($errMsg !== null) {
$this->errMsg = $errMsg;
}
}
public function check($input)
{
if ($this->inclusive && $input >= $this->min && $input <= $this->max) {
return true;
} elseif (!$this->inclusive && $input > $this->min && $input < $this->max) {
return true;
} else {
throw new Exception(sprintf($this->errMsg, $this->min, $this->max));
}
}
}
Example:
$validator = new Validator();
$validator->setRule('name', [new NotEmpty(), new MaxChars(20), new Alpha(true)]);
$validator->setRule('email', [new NotEmpty(), new Email()]);
$validator->setRule('age',
array(
# last constructor argument overrides default error message
new NotEmpty('You did not enter your age.'),
new Numeric('Your age can only be numerical.'),
new Between(13, 17, true, 'Only teenagers are allowed.')
)
);
$validator->validate('name', 'John');
$validator->validate('email', 'Doe');
$validator->validate('age', 'Hello');
# report
if (!$validator->getErrors()) {
echo '<b>Input(s) valid:</b> Passed complete validation.';
} else {
echo '<b>Input(s) invalid:</b> Failed complete validation.';
}
lang-php