Reputation: 831
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
Upvotes: 0
Views: 1363
Reputation: 1018
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.
Upvotes: 0