2010-06-24 42 views
6

我一直在用__invoke魔術方法進行一些測試(替換舊代碼),我不確定這是否是一個錯誤:PHP5.3:調用類變量調用時調用「未定義的方法」錯誤

讓我們假設有一個類:

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() 

我知道,一個「解決方案」可能是有類測試中的功能(名爲k)使用call_user_func_array「轉發」該呼叫,但這不夠優雅。

我需要將該實例保存在一個公共類(用於設計目的)中,並且能夠將其作爲其他類的函數調用......任何建議?

更新:

我發現了一些有趣的事情(我的目的至少):

如果我們分配「類變量」到一個局部變量它的工作原理:

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

請提供一個完整的代碼示例,顯示您的問題。你說的作品的代碼示例不起作用,你說的代碼示例給出了一個問題。 – Sjoerd 2010-06-24 07:54:29

+0

是的,對不起,我的壞...我更新它。 Sjoerd:這個例子是否適合你?奇怪的:S – lepe 2010-06-24 07:56:10

回答

5

當你做爲$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(); 
+0

我們同時發佈了......是的,也許這可以幫助...如果我沒有找到其他更好的替代方案,我會標記你的答案是好的。 – lepe 2010-06-24 08:00:41

6

PHP會認爲你想打電話實例$ T K的方法,當你這樣做:

$t->k(4, 5) 

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

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

又見bug #50029,這說明您的問題。

+0

+1查找bug – Gordon 2010-06-24 08:07:39

+0

(+1)。現在它已經越來越清晰了。謝謝你的鏈接。 – lepe 2010-06-24 08:17:30

2

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

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

但它不會按原樣工作。

相關問題