Question

I'm writing a minimal dependency injection class. However, when I try to access a static property inside a static method php gives 'Undefined variable' notice. The code is this:

class DI{
/**
 * @var array $registry Class dependency resolving functions
 */
public static $registry = [];

/**
 * @var array $instances Class instances for singleton classes
 */
public static $instances = [];

public static function register($className, $singleton, $resolve){
    self::$registry[$className] = ['resolve' => $resolve, 'singleton' => $singleton];
}

public static function inject($className){
    if(array_key_exists($className, self::$registry)){
        if(array_key_exists($className, self::$instances)) {
            return self::$instances[$className];
        }
        else{
            // Problem occurs at that line:
            $instance = self::$registry[$className]['resolve']();
            if(self::$registry[$className]['singleton']){
                self::$instances[$className] = $instance;
            }
            return $instance;
        }
    }
    else{
        return false;
    }
}
}

However if I change that line to these two lines problem disappears:

$instance = self::$registry;
$instance = $instance[$className]['resolve']();

And that is the PHP Notice:

Notice: Undefined variable: registry in /var/www/lib/DI.class.php on line 32
Était-ce utile?

La solution

As you mentioned the problem is the following line:

$instance = self::$registry[$className]['resolve']();

PHP tries to call a function with the name of the string value from the $registry array (not the static class property!). While only a static::$registry array exists, and no local $registry array, php prints the undefined notice.

Because of the function call, PHP resolves this statements like the following pseudo code:

$string = $registry[$className]['resolve'];
$result = $string();
$instance = self::{result of function call}; 

That also is the reason your solution worked. Maybe a static getter method can encapsulate the array acces logic.

There is also a bug filed for this behaviour: https://bugs.php.net/bug.php?id=55573 and an explanation that this is expected to work like it does.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top