簡體   English   中英

PHP5.3:從類變量調用調用時出現“調用未定義方法”錯誤

[英]PHP5.3: “Call to undefined method” error when calling invoke from class variable

我一直在使用__invoke magic方法進行一些測試(以替換舊代碼),但我不確定這是否是錯誤:

假設我們有一個類:

class Calc {
    function __invoke($a,$b){
        return $a*$b;
    }
}

以下是可能的,並且可以正常工作:

$c = new Calc;
$k = $c;
echo $k(4,5); //outputs 20

但是,如果我想讓另一個類存儲該對象的實例,則無法正常工作:

class Test {
    public $k;
    function __construct() {
        $c = new Calc;
        $this->k = $c; //Just to show a similar situation than before
        // $this-k = new Calc; produces the same error.
    }
}

當我們嘗試像這樣調用時會發生錯誤:

$t = new Test;
echo $t->k(4,5); //Error: Call to undefined method Test::k()

我知道“解決方案”可能是在Test類(名為k)中具有一個函數,以使用call_user_func_array“轉發”調用,但這並不優雅。

我需要將該實例保留在一個公共類中(出於設計目的),並能夠從其他類中將其作為函數調用...有什么建議嗎?

更新:

我發現了一些有趣的東西(至少出於我的目的):

如果我們將“類變量”分配給局部變量,它將起作用:

$t = new Test;
$m = $t->k;
echo $m(4,5);

PHP認為您要在實例$ t上調用方法k:

$t->k(4, 5)

這是完全合理的。 您可以使用中間變量來調用對象:

$b = $t->k;
$b(4, 5);

另請參見錯誤#50029 ,它描述了您的問題。

當您執行$test->k() ,PHP認為您正在$test實例上調用一個方法。 由於沒有名為k()方法,PHP會引發異常。 您想要做的是使PHP返回公共屬性k並調用它,但是要這樣做,您必須首先將k分配給變量。 這是取消引用的問題。

您可以將魔術__call方法添加到Test類中,以檢查是否存在帶有被調用方法名稱的屬性,並通過以下方式調用該屬性:

public function __call($method, $args) {
    if(property_exists($this, $method)) {
        $prop = $this->$method;
        return $prop();
    }
}

我將在調用中添加參數。 您可能還需要檢查屬性是否為is_callable

但是無論如何,你可以做

$test->k();

您不能使用方法語法(例如$ foo-> bar())來通過__invoke調用閉包或對象,因為引擎始終認為這是方法調用。 您可以通過__call模擬它:

function __call($name, $params) {
  if(is_callable($this->$name)) {
    call_user_func_array($this->$name, $params);
  }
}

但它不能按原樣工作。

如果您調用$ test-> k(),PHP將在$ test實例上搜索一個名為“ k”的方法,顯然它將引發Exception。

要解決此問題,您可以創建屬性“ k”的吸氣劑

class Test {
    public $k;

    function __construct() {
        $c = new Calc;
        $this->k = $c; //Just to show a similar situation than before
        // $this-k = new Calc; produces the same error.
    }

    public function getK() {
        return $this->k;
    }
}

因此,現在您可以按以下方式使用函子:

$t = new Test();
echo $t->getK()(4,5);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM