Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call __call instead of __callstatic in same class, not if call another class

I have a question about a strange comportement.

Look at this code :

class User
{
    public function can($name) {
        return call_user_func(array($name, 'test'));
    }

    public static function __callStatic($name, $args) {
        return 'User::__callStatic';
    }

    public function __call($name, $args) {
        return 'User::__call';
    }
}

class Foo
{
    public static function __callStatic($name, $args) {
        return 'Foo::__callStatic';
    }

    public function __call($name, $args) {
        return 'Foo::__call?';
    }
}

$u = new User();
var_dump($u->can('User'));
var_dump($u->can('Foo'));

The results of the first var dump is : "User::__call" And the second : "Foo::__callStatic"

Why the first one don't call the function __callStatic ?

PS : I look at other topics, but not found an explaination.

Thanks

like image 642
Ashgan Killigan Avatar asked Sep 01 '17 13:09

Ashgan Killigan


1 Answers

This is just a problem of scope when you call the call_user_func.

When you first call the can function you are in the class User context and it will take __call. In the second call your context is from outside the second class, so therefore it takes the __callStatic. Check callback manual and call-user-func.

For instance code:

<?php

class User
{
    public function can($name) {
        return call_user_func(array($name, 'test'));
    }

    public static function __callStatic($name, $args) {
        return 'User::__callStatic';
    }

    public function __call($name, $args) {
        return 'User::__call';
    }
}

class Foo
{
    public function can($name) {
        return call_user_func(array($name, 'test'));
    }

    public static function __callStatic($name, $args) {
        return 'Foo::__callStatic';
    }

    public function __call($name, $args) {
        return 'Foo::__call?';
    }
}

    function can($name) {
        return call_user_func(array($name, 'test'));
}

$u = new User();
$f = new Foo();
var_dump($u->can('User'));
var_dump($u->can('Foo'));
var_dump($f->can('User'));
var_dump($f->can('Foo'));
var_dump(can('User'));
var_dump(can('Foo'));

will return:

string(12) "User::__call" 
string(17) "Foo::__callStatic" 
string(18) "User::__callStatic" 
string(12) "Foo::__call?"
string(18) "User::__callStatic"
string(17) "Foo::__callStatic"
like image 175
Edwin Avatar answered Oct 01 '22 02:10

Edwin