Press "Enter" to skip to content

PHP's Calling Scope

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

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.