1

I am trying to implement validation functionality on a website on which i am working.

I have created an interface entitled Validator which my classes then implement. The single function in my interface is validate($input).

Then I have a class e.g EmailValidator which now implements this. In its implementation of validate() it checks if the input is a valid email and returns true or false respectively.

Now.. I want to implement a check whereby two inputs are sent and I check if they are equal. For example in the case of passwords. As this interface function only takes one input it is not suitable.

I can create a second interface with a validate function which takes two inputs e.g PairValidator. Is this however the optimal way to implement what i want?

My concern arise because due to the possibility of validation functions i may need i could plausibly have loads of interfaces e.g SetValidator for checking if a value is in a set..

Thanks

5
  • You can make methods in the class that aren't declared in the interface. Commented May 21, 2013 at 15:13
  • I don't think interface implementation is the answer here. Consider just having a utility Validator class which has methods to validate different field types. Commented May 21, 2013 at 15:16
  • What you could do is just present the multiple value to validate to the validator as an array like $validator->validate(array("val1"=>"Test", "val2"=>"Test2"); Commented May 21, 2013 at 15:18
  • @Orangepill I think you read my comment wrong! That's what I said. Commented May 21, 2013 at 15:19
  • @JordanDoyle Sorry about that... Commented May 21, 2013 at 15:21

2 Answers 2

1

There are a couple of ways that you can go with this. A couple of easy ones to that won't break your current interface definition are:

1) Present what needs to be validated as an array.

$validator->validate($_POST["password"],$_POST["password_repeat"]);

2) construct the validator with one of the values that you need.

$validator = new ValidateEquals($_POST["password"]);
$validator->validate($_POST["password_repeat"]);

one way that you can do that would break your current interface and would require changing any validators you have now would be to remove the parameter altogether from the interface definition and use position parameters via func_get_args

interface Validator {
    public function validate();
}

class EqualsValidator implements Validator {
    public function validate(){
        $args = func_get_args();
        return $args[0] == $args[1];
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

IMO, the 2nd suggestion is the best one. This way, you don't need to mess up the interface every time the validation rules changes.
It all depends if the validators are used in a static sense then version two is out. Version 3 is the most flexible but you lose a lot of compile time checks.
What do you mean with "in a static sense"?
I mean instance where user would say EmailValidator::validate($email);
Well, that's why we maybe should not use static for this purpose. By using this, we now loose the capability of automate and chain validators. It could make sense, since validators usually do not have state, but we loose flexibility. And also, in this case, there would be no need for an interface.
0

I have solved the same problem with following interface method:

public function isValid($value, array $values = array());

$values has all form fields as associative array available. So you can work with these values if you need to.

My equal validator looks like:

class Equal implements IValidator
{
    private $_varname = null;

    public function __construct($varname)
    {
        $this->_varname = $varname;
    }

    public function isValid($value, array $values = array())
    {
        if (!array_key_exists($this->_varname, $values)) {
            // set error message
            return false;
        }

        $otherValue = $values[$this->_varname];

        if ($value != $otherValue) {
            // set error message
            return false;
        }
        return true;
    }
}

So I set the other form key to be checked in the constructor.

2 Comments

Interesting. And if i want to reuse the instance of the class simply add a setter method so I could change $_varname? Likewise for checking if a value is in a set are you proposing using exactly the same whereby you set the set array in the constructor and then validate against it in the function?
Yes..exactly, this is how my InArray validator works. If you like you can make a setter for the private fields but I had no needs to reuse an validator instance. And I don't like it because the interface make not much sense if you have methods that aren't declared in the interface.

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.