Handling errors when dynamically creating class methods in PHP

In PHP, it is possible to dynamically create class methods using by implementing the magic __call() method on a class. This function will then be called when accessing a method that is not visible in the current scope, e.g. a private method outside the object’s scope or a non-existent method. PHP will pass the called method’s name as the first argument and an array of arguments as the second argument.

Many programmers assume that when the __call() method returns false, this will indicate to the PHP interpreter that the requested method is not (dynamically) available and that the normal error handling will then take over and trigger an E_FATAL error.

This is not the case in PHP! The method call will complete successfully, returning false. So if you make a typo or whatever there will not be an error, but it will silently succeed. This is a bit unintuitive, because in other cases returning false will trigger the default behavior in PHP. For example, if you set a custom error handler and have it return false, the normal error handler will take over. But with overloading methods this works a bit different.

The best way to deal with this is by raising an error or throwing an exception from the __call() method whenever you are unsure what to do with the dynamic method call. The Standard PHP library provides the excellent BadMethodCallException, which you can throw when there is a – you guessed it – bad method call.

An example with dynamic getters and setters:

class a {
    private $foo = "bar";
    public function __call($method, $args) {
        $property = substr($method,3);
        if (substr($method, 0, 3) == 'get' && isset($this->$property)) {
            return $this->$property;
        }

        if (substr($method, 0, 3) == 'set' && isset($this->$property)) {
            $this->$property = $args[0];
            return;
        }
        throw new BadMethodCallException();
    }
}

About this entry