I'm havinh a problem on PHP 5.3. I need to call a method by using __callStatic
, but if I use it in a instancied object, PHP call __call
instead.
Above a real life example:
<?php
class A {
function __call($method, $args){
// Note: $this is defined!
echo "Ops! Don't works. {$this->c}";
}
static function __callStatic($method, $args){
echo 'Fine!';
}
}
class B extends A {
public $c = 'Real Ops!';
function useCallStatic(){
static::foo();
// === A::foo();
// === B::foo();
}
}
$foo = new B();
$foo->useCallStatic();
// This works:
// B::foo();
?>
Prints: Ops! Don't works. Real Ops!
Note that I call useCallStatic
from a new B()
. If I call directly works fine like B::foo()
.
What I can do to it works fine?
Good news
I make a BIG work arround, but it works pretty fine. This is the code:
You need to call
NoContext::call
(statically) like you callcall_user_func
or similar. It will to remove the$this
context. I still thinks that it is a PHP bug, but...To solve my problem, I do:
And it will prints:
Fine!
.Thanks everybody that help me. I really learn too much with your replies and I wait that my tips be userful sometime to you.
After thinking about it, it's not really a bug. But it's definitely unintuitive.
This is valid, and calls bar(). It does not mean call bar statically. It means to look up the current class name and call function
bar
if it exists, whether or not it's a static function.To clarify a bit more: do you think
parent::bar()
means to call a static function calledbar()
? No, it means call whatever function is namedbar()
.Consider:
The
parent::nonExistant()
method invokesA::__call()
, as doesstatic::nonExistant()
. InvokingA::__callStatic()
for either call would be equally as valid! There is no way for PHP to know which one you want to be called. However, by design, PHP gives__call
the priority when invoked from this sort of context.parent::regularMethod()
invokes the non static functionregularMethod()
. (Again, the::
operator does not mean "call this static function.") Likewiseparent::staticMethod()
invokesA::staticMethod()
as one might expect.To solve your problem:
You could manually call
self::__callStatic('foo')
in the inherited class.Or within the
__call
method of class A filter against a known list and callself::__callStatic
.It's ugly, but at least people who extend the class won't need to do anything special.
First, make sure you're using PHP 5.3.0 or newer, as that's when __callStatic was implemented. It all seems to work as expected, see this example:
The output should be (or at least, it is for me):
When I run your example above, I just get "Fine!" as the only output, which is exactly what I would have expected.
Exactly what version of PHP are you running? You can check with this:
This is probably due to the standard notation of calling parent methods, regardless of state. You could check if the
$this
keyword is set in the__call
method and if not, make a call to__callStatic
?EDIT: This isn't a bug per se, the static call is being made from an object context. Take a look at this bug thread on php.
Inheritance of static methods is a bit weird in PHP. I suspect you need to redefine
__callStatic
inB