Search code examples
phpstatic-methodsprivate-memberslate-static-bindingscope-resolution-operator

Why does PHP execute method of "A" if static:: be resolved to "B"


In this example it first searches in B (because static:: resolves to B) and as it does not find it, it now searches in "A" and that is why it succeeds, right? or am I wrong?

class A {
    private function foo() {
        echo "success!\n";
    }
    public function test() {
        $this->foo();
        static::foo(); // Why does it execute method of "A" if static:: be resolved to "B"?
    }
}

class B extends A {
   /* foo() will be copied to B, hence its scope will still be A and
    * the call be successful */
}
$b = new B();
$b->test();

OUTPUT:

success! success!

Solution

  • Late static binding allows you to refer to the called object's class instead of the class where the method is defined in. But it doesn't change how the scope is resolved, which means that the property/method visibility rules are obeyed as they would if you used self. When you use static, the name of the class will be resolved using runtime information.

    For more information read late static bindings on php.net.

    In your case when you have this:

    public function test()
    {
        $this->foo();
        static::foo();
    }
    

    It's actually the same as this when called on an instance of B:

    public function test()
    {
        $this->foo();
        B::foo();
    }
    

    Upon execution, PHP will start resolving the scope starting with B class. If B doesn't have a method with that name, it will check its parent, and so on. Your B class doesn't have method foo, but A does. So when you execute it, PHP will effectively try to execute something like this:

    public function test()
    {
        $this->foo();
        A::foo();
    }
    

    Now you can see that both lines are the same. The both call the same private method of A class. Yes, the method is private but it's called from within its own class.