【问题标题】:Cannot use invoke magic method within another object不能在另一个对象中使用调用魔术方法
【发布时间】:2013-04-08 21:07:18
【问题描述】:

我遇到了一些我认为是错误的事情,但我不确定。所以我来这里问问比我更了解这个的人,这是PHP的bug吗?看下面几行:

<h1>Tests</h1>

<?php
class Foo
  {
  public function __invoke()
    {
    return 'Called correctly';
    }
  }

class Boo
  {
  public function __construct()
    {
    $this->Foo = new Foo();
    }
  }

$Foo = new Foo();
echo $Foo();

echo "<br><br><hr><br><br>";

$Boo = new Boo();
echo $Boo->Foo();

根据the specification,由于The __invoke() method is called when a script tries to call an object as a function,我应该得到这个:

正确调用


正确调用

但是最后一个回显没有被执行。相反,我得到了这个:

PHP 致命错误:在第 26 行的 [...]/index.php 中调用未定义的方法 Boo::Foo()

这是一个错误还是预期的行为?如果这是一个错误,我们将非常感谢您提供有关如何提交它的帮助。

根据 Jon 的回答进行编辑以进一步显示丑陋的行为

class Doo
  {
  public function __construct()
    {
    // The Foo class is the same as the one defined before

    $Test = new Foo();
    echo $Test();      // Echos correctly

    echo "<br><br><hr><br><br>";

    $this->Foo = $Test;
    echo $this->Foo();  // Error. Heisenbehaviour?
    }
  }

$Boo = new Doo();

【问题讨论】:

    标签: php specifications magic-methods


    【解决方案1】:

    这不是一个错误,它不仅限于Foo 是定义__invoke 的对象。任何可调用对象都会出现相同的错误:

    class Foo
    {
        private $bar = 'rand';
    
        public function __construct()
        {
            $this->bar(); // won't work
        }  
    }
    

    你需要把它写成两行,或者使用call_user_func

    // #1
    $Boo = new Boo();
    $Foo = $Boo->Foo;
    $Foo();
    
    // #2
    $Boo = new Boo();
    call_user_func($Boo->Foo);
    

    【讨论】:

    • bar 只是一个属性。根据我放置的文档链接,Boo 中的对象Foo 如果作为函数调用,将调用它自己的方法__invoke()。没有什么可以让bar 也可以作为一个函数......
    • 这就是变通办法奏效的原因。但是想想你所建议的后果:编译器什么时候应该按照你的建议处理这个构造?显然不是当有方法Bar::Foo 时,所以只剩下没有这种方法的情况。您是在暗示相同的语法最终可能会根据方法的存在或不存在而做两种不同的事情之一?这听起来不是一个好主意。另外,如果既没有属性也没有方法应该怎么办?编译器应该调用__call 还是__get
    • 我知道这不是一个好主意,但它是否比我刚刚进行的编辑的行为更好?根据存储位置改变行为的对象?
    • @FrankPresenciaFandos:我同意它很难看,但是有两种方法可以解析它,编译器只需要选择其中一种。如果有一个合适的方法 Foo() 并且因为还有一个名为 Foo 的属性而没有被调用,你会喜欢它吗?
    • 绝对不是...好吧,那不是错误,只是一个非常丑陋的工作功能,规范中没有明确说明。
    【解决方案2】:

    另见class variable functions

    它有完全相同的问题。 PHP 词法分析器始终将语法 variable T_OBJECT_OPERATOR T_STRING function_call_parameter_list 识别为方法调用。

    【讨论】:

    • 它实际上看起来像同样的问题,但这是面向对象和程序的。
    • 完全正确。如果你用 __invoke、匿名函数或像 ["class", "method"] 之类的回调来做这件事......都是一样的。
    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多