2013-09-24 36 views
-2

我正在PHP中編寫api。 我有一個基類implemets神奇功能__callPHP錯誤:基類函數調用派生類

class Controller 
{ 
    public function __call($name, $arguments) 
    { 
     if(!method_exists($this,$name)) 
      return false; 
     else if(!$arguments) 
      return call_user_func(array($this,$name)); 
     else 
      return call_user_func_array(array($this,$name),$array); 
    } 
} 

和子類是這樣的:

class Child extends Controller 
{ 
    private function Test() 
    { 
     echo 'test called'; 
    } 
} 

所以,當我這樣做:

$child = new Child(); 
$child->Test(); 

和負載該頁面花費大量時間,並且在一段時間後,Web瀏覽器打印該頁面不能被請求。沒有輸出從PHP給出,只有網絡瀏覽器錯誤。

Apache的錯誤日誌(最後一部分只):

... 
[Tue Sep 24 12:33:14.276867 2013] [mpm_winnt:notice] [pid 1600:tid 452] AH00418: Parent: Created child process 3928 
[Tue Sep 24 12:33:15.198920 2013] [ssl:warn] [pid 3928:tid 464] AH01873: Init: Session Cache is not configured [hint: SSLSessionCache] 
[Tue Sep 24 12:33:15.287925 2013] [mpm_winnt:notice] [pid 3928:tid 464] AH00354: Child: Starting 150 worker threads. 
[Tue Sep 24 12:38:43.366426 2013] [mpm_winnt:notice] [pid 1600:tid 452] AH00428: Parent: child process exited with status 3221225725 -- Restarting. 
[Tue Sep 24 12:38:43.522426 2013] [ssl:warn] [pid 1600:tid 452] AH01873: Init: Session Cache is not configured [hint: SSLSessionCache] 

我無法找到的錯誤,但如果功能測試是保護一切工作正常。

溶液中發現:

public function __call($name, $arguments) 
{ 
    if(!method_exists($this,$name)) 
     return false; 
    $meth = new ReflectionMethod($this,$name); 
    $meth->setAccessible(true); 
    if(!$arguments) 
     return $meth->invoke($this); 
    else 
     return $meth->invokeArgs($this,$arguments); 
} 
+0

大家知道,你的英語比我認識的母語人士要好。 – nickb

+1

你應該只能調用在類之外公開的函數,除非你使用反射:http://php.net/reflectionmethod.setaccessible –

+0

謝謝你nickb :) – Naibaf

回答

0

此行爲是一個問題記錄在documentation of method_exists()(錯誤):method_exists()返回true,即使方法是私有/保護,因此,不能從類的外部訪問。這會導致無限遞歸,因爲您的Child->Test()調用調用Child::__call(),它會檢查Test()是否存在(它確實,但不能調用),然後嘗試調用它,這又調用__call()。意見建議使用get_class_methods()可能會解決此問題。我不確定爲什麼將Test()更改爲private的可見性會改變您所述的行爲。

0

Test()公衆的知名度,它應該工作。

我不完全確定爲什麼私人可見性會導致500錯誤(而不是Call to private method...),但我懷疑這是與涉及__call()函數的遞歸有關。 PHP中的一些功能比弊端更壞 - 你真的需要它嗎?

+0

與公衆一起工作,但我的目標是在公共場合工作:)。 – Naibaf