Magic Call Methods & Static Context in PHP
1 min read

Magic Call Methods & Static Context in PHP

PHP's dynamic nature makes it an extremely flexible language. It can also mean confusion if you don't understand the inner workings and/or logic behind the "magic".

Today, I learned an intriguing thing about the magic methods __call() & __callStatic()and class inheritance. Consider the following example:

class Base
{
    public function __call($name, $arguments)
    {
        var_dump(__METHOD__, $this, $name, $arguments);
    }

    public static function __callStatic($name, $arguments)
    {
        var_dump(__METHOD__, $name, $arguments);
    }
}

class Child extends Base
{
    public function doSomething()
    {
        Base::unknownStaticMethod();
    }
}

$child = new Child();
$child->doSomething();

Here, we're making a static method call to Base from within the Child class. Base doesn't have the method, so you'd expect __callStatic() to be called, right? Nope.

string(12) "Base::__call" object(Child)#2 (0) { } string(19) "unknownStaticMethod" array(0) { }

For some reason, __call() is hit with the current class context of our $child object. Why?

When PHP analyzes this code, it makes an important association: Base is the parent of the current object class Child. So, when it sees the call to Base::unknownStaticMethod(), it is interpreted and processed as parent::unknownStaticMethod().

More on parent from php.net:

Three special keywords self, parent and static are used to access properties or methods from inside the class definition.

"Inside the class definition" is a very important distinction. Referencing back to the magic methods documentation:

__call() is triggered when invoking inaccessible methods in an object context.
__callStatic() is triggered when invoking inaccessible methods in a static context.

"Class definition" and "object context" are referring to the same context of an instantiated class.

Unless you're doing some really fancy things with inheritance and magic methods, this probably won't affect your average project. It is helpful to understand how PHP handles object context, especially related to inheritance. Late static bindingis also very on-topic, so read more about it if you're interested in this topic.

Cheers to Sheng Slogar for asking about this topic.