2009-10-01 92 views
14

我正在處理的項目包含一些類似於call_user_func(_array)的包裝,它在執行前執行一些檢查。 其中一個檢查是method_exists(如果提供的第一個參數是一個類的實例,第二個參數是方法名) 另一個is_callable。 如果其中一個檢查失敗,該函數將引發異常。PHP __call vs method_exists

我的代碼包含一個包含函數名稱(setFoo,setBar等)的數組以及用於重載(__call)的php magic函數,它處理某些變量(更好的某些數組元素)的設置,替換和刪除操作。

問題: 如果函數未定義,則method_exists將返回false。

如果__call函數能正確處理請求,我是否有機會獲得true?

+0

大的問題,我會玩這個。 –

+0

需要的是另一種「魔法」__canCall或其他東西...... –

+1

is_callable()適用於類的實例。我不明白你爲什麼使用method_exists()。 is_callable()完成一切method_exists()的工作,加上它可以與__call()一起工作。 – dave1010

回答

4

method_exists嘗試兩件事情:

  • 搜索在類的函數表的方法名。這些是function foo() {}類型的方法。
  • 檢查類(C代碼)是否有(C代碼)get_method()函數,以及是否調用它來讓類實現決定。

你需要後者。但是這個get_method()沒有「擴展」到php腳本代碼中,即沒有辦法讓get_method()調用一些用戶定義的php腳本代碼(這個php代碼會返回什麼?)。

所以我最好的知識的答案是:不,這是不可能的(但?)。

ZEND_FUNCTION(method_exists)的實現可以在zend/zend_builtin_functions.c中找到,我認爲即使您不知道C但是PHP也是相當可讀的。

5

看一看is_callable()

但是不,如果__call()方法只處理一些名字,那麼你需要一些其他的方式來檢查這個調用是否會成功。

可能我建議與方法canCall($function)或什麼的接口?然後檢查類是否實現了接口。如果沒有,只需使用is_callable()

+2

如果定義了__call(),is_callable()將自動返回true,使is_callable()不可支持(因爲它不能確保__call()滿足請求) –

8

__call處理對不存在的方法的調用。 method_exists是檢查方法的存在的反省方法。

__call如何確定處理方法?我認爲你必須在__call中手動拋出一個異常,如果它不處理你的請求並且捕獲代碼中的異常,否則它將使用method_existsBadMethodCallException爲此存在。

+1

似乎'__call'沒有「失敗」的概念,所以它看起來像在__call方法中拋出一個'NotImplementedException'(或類似的)將是這樣做的方式。 –

1

我會被誘惑,也許用在你的__call功能method_existsthrowException如果失敗,並在trycatch塊,而不是使用is_callable功能包的一切。

1

如果你真的確信_call總是有一個回退,你可以這樣做:

if (method_exists($this, $method_name) || method_exists($this, '__call')) { 
    // Call of the method 
}