2011-02-08 111 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); 
    } 
} 
相关问题