【问题标题】:PHP Callable Object as Object MemberPHP 可调用对象作为对象成员
【发布时间】:2010-12-11 23:39:38
【问题描述】:

我有一个类Logger,其中有一个方法Log
由于LogLogger 实例最常见的用法,我已连线__invoke 以调用Log

另一个类“Site”包含一个成员“Log”,它是 Logger 的一个实例。

为什么会这样:

$Log = $this->Log;  
$Log("Message");  

但不是这个:

$this->Log("Message");

前者因“PHP 致命错误:调用未定义方法 Site::Log()”而失败
这是可调用对象实现的限制,还是我误解了什么?

【问题讨论】:

    标签: php invoke callable


    【解决方案1】:

    不幸的是,这(仍然)是 PHP 的一个限制,但仔细想想它是有道理的,因为一个类可以包含共享名称的属性和方法。例如:

    <?php
    class Test {
        public $log;
    
        public function __construct() {
            $this->log = function() {
                echo 'In Test::log property';
            };
        }
    
        public function log() {
            echo 'In Test::log() method';
        }
    }
    
    $test = new Test;
    $test->log(); // In Test::log() method
    call_user_func($test->log); // In Test::log property
    ?>
    

    如果 PHP 允许使用您想要的语法,会调用哪个函数?不幸的是,这只给我们留下了call_user_func[_array]()(或将$this-&gt;log复制到另一个变量并调用它)。

    但是,如果以下语法是可以接受的,那就太好了:

    <?php
    {$test->log}();
    ?>
    

    可惜不是这样的。

    【讨论】:

    • 这确实是一个奇怪的怪癖。 ($test->log)() 之类的东西似乎主要是解析器的限制,而不是语言本身的限制。
    【解决方案2】:

    同样的原因你不能这样做:

    $value = $this-&gt;getArray()["key"];

    甚至这个

    $value = getArray()["key"];

    因为 PHP 语法不擅长速记。

    【讨论】:

    • 主要是因为松散的打字。没有办法真正推断出你可能要做什么,所以它默认是提前出错。
    • 我写了一个奇怪的预解析器,它允许编写这样的表达式:code.google.com/p/php-preparser :)(我可以在这里“宣传”我的开源解决方案吗?)
    【解决方案3】:

    这可能有效:

    ${this->Log}("Message");
    

    但也许使用完整的调用更容易更好?似乎没有一种方法可以在一条线上获得您想要的工作。

    您问题中的错误表明它正在寻找在不存在的类上定义的函数。可调用对象不是函数,在这种情况下似乎不能被视为一个函数。

    【讨论】:

    • 将不起作用(至少对我而言,php 5.3 不适用)»意外的 T_OBJECT_OPERATOR ...«
    【解决方案4】:

    从 php7.4 开始,以下代码适用于我

    ($this->Log)("Message");
    

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 2014-01-15
      • 1970-01-01
      • 2017-12-29
      • 2012-10-29
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多