__call,__ callStatic和PHP中的调用范围

时间:2013-08-28 12:26:11

标签: php

我最近阅读过在PHP中调用范围和范围解析运算符(::)。有两种变体:实例调用和静态调用。考虑下面的听法:

<?php

class A {
    public function __call($method, $parameters) {
        echo "I'm the __call() magic method".PHP_EOL;
    }

    public static function __callStatic($method, $parameters) {
        echo "I'm the __callStatic() magic method".PHP_EOL;
    }
}

class B extends A {
    public function bar() {
        A::foo();
    }
}

class C {
    public function bar() {
        A::foo();
    }
}

A::foo();
(new A)->foo();

B::bar();
(new B)->bar();

C::bar();
(new C)->bar();

执行结果(PHP 5.4.9-4ubuntu2.2)是:

I'm the __callStatic() magic method
I'm the __call() magic method
I'm the __callStatic() magic method
I'm the __call() magic method
I'm the __callStatic() magic method
I'm the __callStatic() magic method

我不明白为什么(new C)->bar();执行__callStatic()的{​​{1}}?实例调用应该在bar()方法的上下文中进行,不是吗?是PHP的功能吗?

Addition1:

此外,如果我不使用魔术方法并明确调用,一切都按预期工作:

A

结果:

<?php

class A {
    public function foo() {
        echo "I'm the foo() method of A class".PHP_EOL;
        echo 'Current class of $this is '.get_class($this).PHP_EOL;
        echo 'Called class is '.get_called_class().PHP_EOL;
    }
}

class B {
    public function bar() {
        A::foo();
    }
}

(new B)->bar();

2 个答案:

答案 0 :(得分:3)

bar()的{​​{1}}方法中,您有C

A::foo();

由于此方法既未创建public function bar() { A::foo(); } 的实例,也未A扩展C,因此A运算符被视为试图调用的静态运算符静态方法::。由于A::foo()未定义foo(),因此它会回落到A方法。

如果您希望它在不延长__callStatic()的情况下调用非静态方法,则必须创建A的实例:

A

答案 1 :(得分:0)

这是因为在这种情况下我们没有A类的实例。 注意

 class B extends A

因此,new B可让我们访问{静态版A->foo

C不会扩展A,因此只有A的静态方法可用。