6

im am making a php validation class with sub classes that extend it, eg, mobile, suburb, credit_card, ect

so, the idea is you can call

$validation = new Validation('mobile');
$valid = $validation->validate($number);

$validation->type('suburb');
$valid2 = $validation->validate($suburb);

now my idea for doing this is having

class Validation() {
    private $v_type = null;

    function __construct($type) {
        $this->type($type);
    }

    public function type($type) {
        $this->v_type = new $type();
    }

    public function validate($info) {
        return $this->v_type->validate($info);
    }
}

as a very basic example

but is there a better way of doing this?

3 Answers 3

9

You could do it this way, but it could be improved. Having the actual validators capsule their own validation logic is good. Extending them from a base class isn't. Let's implement an interface instead. This way, any class can be a Validator.

interface IValidate
{
    public function validate($value);
}

Your validators would look like this then:

class IsNumeric implements IValidate
{
    public function validate($value)
    {
        return is_numeric($value);
    }
}

and

class GreaterThan implements IValidate
{
    protected $_value;
    public function __construct($value)
    {
        $this->_value = $value;
    }
    public function validate($value)
    {
        return $value > $this->_value;
    }
}

You'd still have a main Validator class. Unlike in your example, the Validator below accepts multiple Validators, which will allow you to create a Filter Chain.

class Validator implements IValidate
{
    protected $_validators;

    public function addValidator(IValidate $validator)
    {
        $this->_validators[] = $validator;
        return $this;
    }
    public function validate($value)
    {
        foreach($this->_validators as $validator) {
            if ($validator->validate($value) === FALSE) {
                return FALSE;
            }
        }
        return TRUE;
    }
}

And this could be used like:

$validator = new Validator;
$validator->addValidator(new IsNumeric)
          ->addValidator(new GreaterThan(5));

var_dump( $validator->validate('ten') ); // FALSE
var_dump( $validator->validate('10') );  // TRUE
var_dump( $validator->validate('1') );   // FALSE

The above is pretty much a Command pattern. And due to the Validator implementing IValidate as well, it is also a Composite. You could take the Validator chain from above and stack it into another Validator Chain, e.g.

$numericGreaterThanFive = new Validator;
$numericGreaterThanFive->addValidator(new IsNumeric)
                       ->addValidator(new GreaterThan(5));

$otherValidator = new Validator;
$otherValidator->addValidator(new Foo)
               ->addValidator(new Bar)
               ->addValidator($numericGreatherThanFive);

For convenience, you could add a static factory method for creating Validators with the actual Validation Command objects (as shown elsewhere).

On a sidenote: the Zend Framework already has an extensive number of Validators you can build on. Since ZF is a component library, you can use them without having to migrate your entire application to ZF.

Sign up to request clarification or add additional context in comments.

Comments

2

Usually you do these kind of things using the Factory pattern, something like this:

class ValidatorFactory {
    public static function get($type) {
        $validator = "Validator_$type";
        return new $validator();
    }
}

$valid = ValidatorFactory::get('mobile')->validate($number);

Would of course need some error checking and such, but you should get the idea

Comments

0
...
public function type($type) {
    return new self($type);
}
...

Note: This one every time returns a new instance of your Validator class so it would be a better idea to use the Factory pattern as Dennis suggested or not to tie the new Validator to the type() method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.