Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__callStatic does not call if there exist a non-static function

Tags:

php

my code like that:

<?php

class A {

    public function CallA()
    {
        echo "callA" . PHP_EOL;
    }

    public static function CallB()
    {
        echo "callB" . PHP_EOL;
    }

    public static function __callStatic($method, $args)
    {
        echo "callStatic {$method}";
    }
}

A::CallA();

but It will echo :

Strict Standards: Non-static method A::CallA() should not be called statically in /vagrant/hades_install/public/test.php on line 21
callA

that is say, CallA does not run into function __callStatic

how can i do if i want the __callStatic be called by use A::CallA()

like image 702
jianfeng Avatar asked Jun 25 '15 00:06

jianfeng


2 Answers

As the documentation explains:

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

The method CallA() in your code is accessible, this is why PHP does not use __callStatic() and calling CallA() directly is its only option.

You can force the invocation of __callStatic() either by making CallA() inaccessible (rename it or change its visibility to protected or private) or by calling it directly (ugly workaround):

A::__callStatic('CallA', array());

If you choose to make CallA() protected you need to implement the method __call() to be able to call CallA() again:

class A {

    protected function CallA()
    {
        echo "callA" . PHP_EOL;
    }

    public static function CallB()
    {
        echo "callB" . PHP_EOL;
    }

    public static function __callStatic($method, $args)
    {
        echo "callStatic {$method}" . PHP_EOL;
    }

    public function __call($method, $args)
    {
        if ($method == 'CallA') {
            $this->CallA();
        }
    }
}

A::CallA();
A::__callStatic('CallA', array());

$x = new A();
$x->CallA();

It outputs:

callStatic CallA
callStatic CallA
callA
like image 101
axiac Avatar answered Oct 12 '22 23:10

axiac


Another approach is to keep the non-static method intact and use a prefix when calling it statically, resolving the method name within __callStatic.

class A {

    public function CallA()
    {
        echo "callA" . PHP_EOL;
    }

    public static function __callStatic($method, $args)
    {
        $method_name = ltrim($method, '_');
        echo "callStatic {$method_name}" . PHP_EOL;

        $instance = new A();
        return instance->$method_name(...$args); //this only works in PHP 5.6+, for earlier versions use call_user_func_array
    }

}

A::_CallA();

This will output:

callStatic callA
callA
like image 34
Lucian STUPARU Avatar answered Oct 13 '22 01:10

Lucian STUPARU