Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validating constructor parameters, making sure parameters have the correct type

Writing my first PHP Class and came across an issue, the following is my __construct method:

public function __construct($foo,$bar) {
       $this->foo = $foo;
       $this->bar = $bar;
}

Both $foo and $bar are required, without them, the methods will not work. It's OK when they aren't defined when the object is instantiated like so:

$var = new Class();

As this throws an exception (e.g. Class requires 2 params, none set). But if they are set but not of the correct type like so:

$var = new Class('33','ddd');

My methods will fail as the variables have the wrong type.

Where should I be validating these? In the constructor or in each method?

My solution that I'm using right now works, but I'm not sure if it's the right way:

// $foo needs to be a string with letters only
// $bar needs to be an integer
public function __construct($foo,$bar) {
       $this->foo = $foo;
       $this->bar = $bar;
       if(!is_numeric($bar)){
           // Throw exception
       }
       elseif(other validation case)
       etc...
}

The concepts of OO programming are pretty new to me, so links to any reference material you have would be greatly appreciated.

like image 890
Daniel Avatar asked Jan 05 '11 14:01

Daniel


1 Answers

I'd probably do something like this to prevent clutter inside the ctor and to allow the class to set them values internally:

class MyClass …

    protected $_foo;

    /**
     * @param  String   $foo    String with letters only
     * @param  Integer  $bar    Any Integer
     * @return void
     * @throws InvalidArgumentException when $foo is not letters only
     * @throws InvalidArgumentException when $bar is not an Integer
     */
    public function __construct($foo, $bar) 
    {
        $this->_setFoo($foo);
        $this->_setBar($bar)
    }

    /**
     * @param  String   $foo    String with letters only
     * @return void
     * @throws InvalidArgumentException when String is not letters only
     */
    protected function _setFoo($foo)
    {
        if (FALSE === $this->_consistsOfLettersOnly($foo)) {
            throw new InvalidArgumentException(
                '$foo should consists of letters only'
            );
        }
        $this->_foo = $foo;
    }  

    …

This has the added advantage that if you need to publicly expose the setters later, you just have to change the visibility keyword.

Making the validation into it's own method is not strictly necessary, but I think it makes the code more readable. If you find another property in that class needs the same validation, you can also reuse it more easily.

like image 124
Gordon Avatar answered Sep 21 '22 01:09

Gordon