【问题标题】:Why does PHP prefer __call() to __callStatic()?为什么 PHP 更喜欢 __call() 而不是 __callStatic()?
【发布时间】:2016-03-21 18:36:49
【问题描述】:

当我尝试这个时:

<?php
class myParent {
    public function __call($method, $params) {
        echo "from __call";
    }

    public function __callStatic($method, $params) {
        echo "from __callStatic";
    }
}

class mySon extends myParent {
    public function bar() {
        myParent::foo();
    }
}

(new mySon())->bar();

我希望这个输出:from __callStatic ...

相反,它给出:from __call

谁能解释一下为什么?


编辑: 确切地说,我想知道为什么如果我删除 __call 函数,那么它会触发 __callStatic 以及是否有办法在声明 __call 时触发 __callStatic .

【问题讨论】:

  • (new mySon()) 是一个对象。您在该对象上调用了 bar() 方法,该方法为对象的父类调用 foo(),该父类是对象本身的一部分。在任何时候,它都不会对任何东西进行静态引用。
  • 如果你删除 extends myParent - 你会得到你需要的,因为类不再连接。

标签: php


【解决方案1】:

这里发生了两件事,首先:PHP 支持将classname::method 作为parent::method别名,以及一种跳过树as demonstrated here 中某些类的方法。

其次,parent:: 不是静态调用,不可能使用parent::classname:: 静态调用父级的方法。我实际上打开了一个bug report,但这并没有触发任何开发人员将其做得更好。

这两种结合会导致您看到的非直觉行为

【讨论】:

    【解决方案2】:

    您静态调用了函数但在类的实例中。所以 PHP 调用了基于实例的__call()。请注意,此代码在功能上等同于您静态编写的代码

    class mySon extends myParent {
        public function bar() {
            $this->foo(); // works the same way as myParent::foo();
        }
    }
    

    如果你这样称呼它,你会得到静态的(注意,__callStatic() 本身必须是静态的)

    class myParent {
        public function __call($method, $params) {
            echo "from __call";
        }
    
        public static function __callStatic($method, $params) {
            echo "from __callStatic";
        }
    }
    myParent::foo();
    

    【讨论】:

    • 但是为什么当我删除__call 函数时,会调用__callStatic 呢?有什么方法可以从bar() 函数触发__callStatic 吗?
    • @JohnSaucisse 正如在其他 cmets 中提到的,如果您删除 extends,那么该类不再是您尝试静态调用的类的实例。至于为什么在没有__call 的情况下调用__callStatic,可能与操作顺序有关
    【解决方案3】:

    好吧,我为我想做的事情找到了一个明显的解决方案:

    class mySon extends myParent {
        public function bar() {
            myParent::__callStatic('foo', array());
        }
    }
    

    【讨论】:

    • 您问为什么,这已得到解释。解决方法不能解释原因,因此不是问题的有效答案
    猜你喜欢
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 2023-01-16
    相关资源
    最近更新 更多