2013-02-12 79 views
3

我只是在嘲笑我正在開發的一個攔截類。想法是通過Intercept類實例化類,然後使用該對象,就好像它是您正在攔截的類。每次調用該類時都會執行指定的回調。下面是代碼:PHP 5.4次關閉調用

<?php 
class Intercept { 

    protected $class = null; 
    protected $callback = null; 

    public function __construct($class, $callback = null) { 

     $this->class = new $class(); 
     $this->callback = $callback; 
    } 

    protected function run_callback() { 

     $this->callback(); 
    } 

    public function __get($name) { 

     $this->run_callback(); 
     return $this->class->$name; 
    } 

    public function __set($name, $value) { 

     $this->run_callback();  
     return $this->class->$name = $value; 
    } 

    public function __isset($name) { 

     $this->run_callback(); 
     return isset($this->class->$name); 
    } 

    public function __unset($name) { 

     $this->run_callback(); 
     unset($this->class->$name); 
    } 

    public function __call($method, $args) { 

     $this->run_callback(); 
     return call_user_func_array(array($this->class, $method), $args); 
    } 

    public function __toString() { 

     $this->run_callback(); 
     return $this->class; 
    } 

    public function __invoke() { 

     $this->run_callback(); 
     return $this->class(); 
    } 
} 

class test { 
    public function hello() { 
     return 'world'; 
    } 
} 

$closure = function() { 
    echo 123; 
}; 

$test=new Intercept('test', $closure); 
echo $test->hello(); 

現在,上面跑應該顯示 'world123' 的代碼。但由於我看不到的一些奇怪的原因,它最終會超時。我在我的本地機器上以及各種php 5.4測試機站點上嘗試了它。同樣的事情發生。我已經縮小到run_callback()方法中正在運行的閉包($ this-> callback())。如果我只是刪除$ this-> callback(),它工作正常。這是爲什麼發生?

編輯,而我在寫這個問題,我想通了,而不是:

$this->callback(); 

這樣做會停止超時:

$closure = $this->callback; 
$closure(); 

看來,__call方法獲取我每次嘗試直接從類屬性運行閉包。這是預期的行爲,還是我偶然發現了一個PHP錯誤?

+0

[絕對是PHP的問題](http://3v4l.org/qi89N)。如果您發現原因,請在此處張貼。 – 2013-02-12 02:27:02

+0

您是否嘗試過使用xdebug代碼來查看真正發生了什麼? – Rob 2013-02-12 02:27:20

回答

4

很確定這是因爲你的函數調用堆棧有一個無限循環。當你做

$this->callback(); 

你試圖執行成員函數callback(),它不存在,所以__call()得到執行,這將再次嘗試callback(),它不存在,所以__call()被執行,等等等等。

您應該使用的線沿線的東西:

call_user_func($this->callback); 

或者,就像你編輯,這將工作太:

$closure = $this->callback; 
$closure(); 

希望這清除了所發生的事情。超時正在發生,因爲您的資源耗盡(在這種情況下是時間)。根本問題是無限循環。