PHP上的大多数资源从不接触内存管理,因为语言本身非常适合为您执行此操作。但是,在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任务?
答案 0 :(得分:10)
这与Is destructor in PHP predictable?几乎是同一个问题,答案是一样的。 PHP使用refcounting,它承诺一旦refcount变为零(通常当对象超出范围时)就会立即调用析构函数。因此,如果您创建一个对象并注意不要将其泄漏到范围之外,那么RAII就是可行的。
答案 1 :(得分:4)
PHP使用引用计数,因此当您完成变量后,它会立即被清除。 (除非你创建周期。)这会立即释放资源,因此除了小心不创建内存周期之外,通常不需要担心显式资源管理。
如果您确实想要实施任何特定策略,可以通过确保资源仅由一个变量使用来实现。每当该变量指向远离资源时,应立即释放资源。
答案 2 :(得分:2)
当ReturnHandler
的实例超出范围时,以下类ReturnHandler
提供处理程序的自动调用。您可以在函数(return
)中使用多个myfunc
,而无需考虑在每个资源之前释放资源。
/**
* 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);
}
}
答案 3 :(得分:0)
有点题外话:您可以使用lambda做类似using
的模式。像这样:
function WithFile($Name, $Func)
{
$File = fopen($Name, 'r');
$r = $Func($File);
fclose($File);
return $r;
}
然后像这样使用它
$FileHeader = WithFile('myfile', function($File) {return fread($File, 16);});
完全确定的。也就是说,lambdas是否有更简短的语法...