- URL: https://www.laruence.com/en/2012/06/14/2628.html
- Please include attribution when republishing.
Yesterday in the Yaf discussion group, the 大草原 friend criticized me for getting lazy — the blog hasn't been updated in a long time. Today it just so happens someone asked me a question on SegmentFault. I gave a brief answer on Weibo, but I felt a single sentence couldn't explain it clearly, so I'll just write a blog post to pad the count. 😉
The question is here, and since it's too long, I won't copy it over: Is this a bug in PHP where __call and __callStatic produce when inherited?
At first glance, this question is indeed easy to be confused by. But in reality, the root cause of this misunderstanding is: in PHP, determining whether something is static or not is not by the "::" (PAAMAYIM_NEKUDOTAYIM) symbol, but by the calling scope.
So, what is a calling scope?
In PHP, when you call a method, the object that the $this pointer points to is the calling scope at the moment the method is invoked. For the example below:
<?php Foo::bar(); ?>
When calling the bar method, it's in a context with no calling scope, so this is a static call.
Whereas for the following example:
<?php
class A {
public function test() {
Foo::bar();
}
}
$a = new A();
$a->test();
When calling the bar method, it's in a context of the $a object — that is, the calling scope at this point is the $a object, so this is actually not a static call.
To verify this conclusion, please look at the following real example:
<?php
class Foo {
public function bar() {
var_dump($this);
}
}
class A {
public function test() {
Foo::bar();
}
}
$a = new A();
$a->test();
?>
What does it output?
object(A)#1 (0) {
}
When calling bar, in this seemingly "static" call, the $this pointer is actually assigned — it points to the $a object. So does this still count as a static call?
I use this example to illustrate the point. But in real applications, you should try to avoid using "::" to call a non-static method. PHP also gives a Strict warning for this kind of call:
Strict Standards: Non-static method Foo::bar() should not be called statically, assuming $this from incompatible context
Some might say this should count as a bug, right? Actually not — it's more the result of misuse, caused by calling a class's non-static method in a "static form" while you're in a context that has a calling scope.
So why is PHP designed this way? Consider the following example:
<?php
class A {
public function __construct() {
}
}
class B extends A {
public function __construct() {
parent::__construct();
}
}
When we call the parent class's constructor, we intentionally want to pass the current scope to the parent's constructor as the calling scope.
Now, do you have a slightly deeper understanding of static calls? The company's all-hands meeting is about to start this afternoon, so this was written in a hurry and may be a bit messy. Please bear with me, hehe, thanks.
Be First to Comment