__callStatic is not called?

class, php, static

Solution

You can not staticfy your object methods through `__callStatic` calls in PHP. It will only be invoked when the method so far does not exist (incl. not being visible from the calling context). In your case `Test::getSomeVar()` is already defined.

Because of backwards compatibility, PHP does not check if only a static method exists, but actually if generally a method exists.

In your case you are calling the non-static method statically, so `$this` is not defined because `__callStatic` has not been invoked. If you would have enabled warnings and notices to the highest level (recommended for development), PHP would have warned you about that.

The correct usage therefore is:

echo Test::instance()->getSomeVar();

As with any other implementation of a Singleton.

So you are just using `__callStatic` wrong, it only works for methods not yet defined. Choose another tool/design for the job, like the aggregation example you use with your `Blah` class.

A further note:

You should normally prevent to use any static context in PHP anyway, especially as you exploit a lot of magic functionality here, too, which is another smell. It looks like you have a pile of design issues before you even finished your code. You will only increase the likelihood to run into hard to debug and maintain code with all this. But that just so you do not say in some time you have not been warned.

See Who needs singletons? in case you want to learn more.

Problem

I know the following could potentially create problems elsewhere and is probably bad design, but I still would like to know why this fails (for my own edification): ``` class Test { // singleton private function __construct(){} private static $i; public static function instance(){ if(!self::$i){ self::$i = new Test(); } return self::$i; } // pass static requests to the instance public static function __callStatic($method, $parameters){ return call_user_func_array(array(self::instance(), $method), $parameters); } private $someVar = 1; public function getSomeVar(){ return $this->someVar; } } print Test::getSomeVar(); ``` The error is `Using $this when not in object context` Obviously $this is unavailable from a static method, but the static method is handing it off to an instance method invokation via call_user_func_array, which should make $this the instance... /EDIT I'm aware that $this is not available in static context. However, this works: `print call_user_func_array(array(Test::instance(), 'getSomeVar'), array());` Which is exactly what's happening in the __callStatic overload, so something's amiss... /EDIT 2 scope is definitely getting handled strangely. if you pull the singleton instance to any other class, it works as expected: ``` class Test { // singleton private function __construct(){} private static $i; public static function instance(){ if(!self::$i){ self::$i = new Blah(); } return self::$i; } // pass static requests to the instance public static function __callStatic($method, $parameters){ return call_user_func_array(array(static::instance(), $method), $parameters); } } class Blah { private $someVar = 1; public function getSomeVar(){ return $this->someVar; } } print Test::getSomeVar(); ```

Original source

Related problems