6

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

5
  • this code works: 3v4l.org/E1gKl Commented Sep 1, 2017 at 13:17
  • @Edwin I know :) This is not my question, I expect to have "User::__callStatic" for the first var dump Commented Sep 1, 2017 at 13:28
  • I posted in response to other comments that now are deleted Commented Sep 1, 2017 at 13:29
  • A good question about a gray area of the PHP OOP. Commented Sep 1, 2017 at 13:48
  • somehow related: stackoverflow.com/questions/18487874/… or this: stackoverflow.com/questions/36139042/… Commented Sep 1, 2017 at 14:08

2 Answers 2

1

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"
Sign up to request clarification or add additional context in comments.

2 Comments

Scope is the wrong word, context is what you're looking for. The question then though is why PHP decides that call_user_func(['User', ...]) in a User context is an instance call, while in another context it's static.
yes context is better. If you will made the can function static it would return the __callStatic, so I think php it's trying to find first the functions on the same level (if this makes sense).
0

Thank you both of you.

Yes this is due to context , is that a bug of PHP (fix in the later version, not in 7.2, so... ;) ) or is it just a strange comportement.

@Edwin I know if I transform the function can() to static, it will work, but I doesnt want to. To resolve the "problem", I call the function __callStatic() in my function can() only in the case of calling self class :

if($name instanceof User) return self::__callStatic($functionName, $args);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.