2011-02-08 72 views
9

PHP上的大多數資源都不會觸及內存管理,因爲語言本身對於爲您做這件事非常好。然而,在PHP中,您通常最終會處理不是內存的外部資源 - 數據庫句柄,會話,數據庫事務等等。這些外部資源可以使用某種形式的RAII對象進行乾淨地管理。PHP支持RAII模式嗎?怎麼樣?

我最初認爲PHP使用了類似於JVM或CLR的垃圾收集方案,其中析構函數的概念不存在。 (記住:Everyone thinks about garbage collection the wrong way - 終結器不是破壞者!)有特殊的__destruct方法,但我認爲這是一個類似於Java或C#終結器的「終結器」。由於這個原因,你不能在JVM或CLR上使用RAII(C#的using塊可以讓你獲得大約95%的路,但這有點不同......)。

但是,Google seems to indicate that PHP supports the RAII pattern,雖然我無法在PHP文檔中找到此驗證。語言是否支持這一點,並且將清理邏輯放在__destruct之內足以完成RAII任務?

回答

9

這與Is destructor in PHP predictable?的問題幾乎相同,答案也是一樣的。 PHP使用refcounting,它承諾一旦引用計數變爲零(通常是當對象超出範圍時),立即調用析構函數。因此,如果您創建一個對象並注意不要將其泄漏到範圍外,則RAII是可行的。

+3

另一個警告:當多個對象在同一時間離開的範圍,它們的析構函數被調用的順序是正式定義,通常在FIFO順序(完全與正確的RAII所需的相反)。這對我的特殊用例來說是一個破壞者。 – Brilliand 2014-01-27 20:29:34

+0

@Brilliand你可以人爲地添加大括號來強制排序? :) – hobbs 2014-01-27 20:53:33

4

PHP使用引用計數,所以當你完成一個變量後,它會立即被清除。 (除非你創建週期。)這樣可以及時釋放資源,因此除了小心不要創建內存週期之外,您通常不需要擔心顯式資源管理。

如果您確實想要實現任何特定策略,可以通過確保資源僅由一個變量使用來實現。只要該變量指向遠離資源,資源應立即釋放。

2

ReturnHandler的實例超出範圍時,以下類ReturnHandler會自動調用處理函數。您可以在您的函數(myfunc)中擁有多個return,而無需在每個函數之前考慮釋放資源。

/** 
* Automatically calls a handler before returning from a function. Usage: 
* 
* function myfunc() 
* { 
* $resource = new Resource(); 
* $rh = new ReturnHandler(function() use ($resource) { $resource->release(); }); 
* // ... 
* if(...) { 
* return; // look, ma, automatic clean up! 
* } 
* } 
*/ 
class ReturnHandler 
{ 
    private $return_handler; 

    public function __construct($return_handler) 
    { 
    $this->return_handler = $return_handler; 
    } 

    public function __destruct() 
    { 
    $handler = $this->return_handler; 
    $handler(); 
    } 
} 

下面是它的測試:

class ReturnHandlerTest extends PHPUnit_Framework_TestCase 
{ 

    private static function trigger_return_handler(&$var) 
    { 
    $rh = new ReturnHandler(function() use (&$var) { $var++; }); 
    } 

    public function test() 
    { 
    $a = 0; 
    $this->assertEquals(0, $a); 
    self::trigger_return_handler($a); 
    $this->assertEquals(1, $a); 
    } 
} 
相關問題