【问题标题】:Unexpected behavior when utilizing __call and __callStatic from different scopes从不同范围使用 __call 和 __callStatic 时的意外行为
【发布时间】:2021-09-13 10:30:26
【问题描述】:

各位字节处理器大家好,

上周我们在 PHP 中偶然发现了一些出乎意料的行为。对于我们的框架,我们利用基类中的 __call __callStatic 魔术函数来提供某种与该线程无关的功能。当我们在同一个类上使用 __callStatic 函数和适当的静态调用时,魔术函数是在对象范围内定义的,由于某种原因,__call 方法将被调用。

这是一个最小的工作示例:

/** tests calls on class B */
class B {
    /** catch object calls on B */
    public function __call($name, $arguments) {
        print("  __CALL on B\r\n");
    }
    /** catch static calls on B */
    public static function __callStatic($name, $arguments) {
        print("  __STATICCALL on B\r\n");
    }
}

/** tests calls on class A */
class A {
    /** catch object calls on A */
    public function __call($name, $arguments) {
        print("  __CALL on A\r\n");
    }
    /** catch static calls on A */
    public static function __callStatic($name, $arguments) {
        print("  __STATICCALL on A\r\n");
    }


    public static function doMagicCall_from_staticContext() {
        // static scope
        A::BLA(); // expect A::__callStatic, works
        B::BLA(); // expect B::__callStatic, works
    }

    public function doMagicCall_from_objectContext() {
        // object scope
        A::BLA(); // expect A::__callStatic, got $this->__call(), prints "__CALL on A"
        B::BLA(); // expect B::__callStatic, works
    }
}


$a = new A();
print("1. Call from static context:\r\n");
A::doMagicCall_from_staticContext();
print("\r\n");
print("2. Call from object context:\r\n");
$a->doMagicCall_from_objectContext(); // provokes the behavior

这将打印:

1. Call from static context:
  __STATICCALL on A
  __STATICCALL on B

2. Call from object context:
  __CALL on A
  __STATICCALL on B

我们预计所有调用都返回“__STATICCALL”。 乍一看,这在我们看来是解释器中的一个错误,因为 PHP 文档明确指出:

__call() 在对象上下文中调用不可访问的方法时触发。

我们测试了不同的解释器,到目前为止,这种行为在我们的测试中是一致的:7.3.10-nts-Win32-VC15-x645.6.40-nts-Win32-VC11 -x868.0.10-nts-Linux-x64

我在 bugs.php.net

上找不到与此相关的任何内容

我的问题是: 这是解释器中的错误还是我们在这里遗漏了什么?

提前感谢德国的问候。

【问题讨论】:

    标签: php


    【解决方案1】:

    我无法回答为什么会发生这种情况,也没有针对您的问题的解决方案。 然而,我确实推测这是这样实现的,因为对父方法的调用是使用静态调用表示法完成的,并且应该在对象的 $this 上触发。 假设您有如下代码设置:

    class A {
        function do() {
            echo "A do";
        }
    }
    
    class B extends A {
        function do() {
            parent::do();
            echo "B do";
        }
    }
    $b = new B();
    $b->do();
    

    这样的输出是:

    A doB do
    

    尽管这可能是原因,但我认为这是无意的,很可能是一个错误。 继续在 bugs.php.net 上提交错误报告,我想你在这里找到了一些东西。

    【讨论】:

    • 感谢您的贡献。好吧,至少我不是唯一一个将其视为错误的人。我将提交一份错误报告,看看那里会发生什么。先生,我会及时通知您。
    【解决方案2】:

    似乎我对 :: (Paamayim Nekudotayim,或者更确切地说范围解析运算符)的实际工作方式有误解。在相同的情况下使用 forward_static_call 仍然存在不一致。 跟进https://bugs.php.net/bug.php?id=81436

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-05
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 2012-01-16
      相关资源
      最近更新 更多