14

PHPのほとんどのリソースは、言語自体がこれを行うのに非常に優れているため、メモリ管理に触れることはありません。ただし、PHPでは、メモリではない外部リソース(データベースハンドル、セッション、データベーストランザクションなど)を処理することがよくあります。これらの外部リソースは、何らかの形式のRAIIオブジェクトを使用して最もクリーンに管理できます。

PHPは、デストラクタの概念が存在しないJVMやCLRと同様のガベージコレクションスキームを使用していると当初は思っていました。(覚えておいてください:誰もがガベージコレクションを間違った方法で考えています-ファイナライザーはデストラクタではありません!)特別な__destruct方法がありますが、それはJavaやC#ファイナライザーに似た「ファイナライザー」だと思いました。このため、JVMまたはCLRでRAIIを使用することはできません(C#のusingブロックはそこまでの道のりの約95%を取得しますが、それは少し異なります...)。

ただし、GoogleはPHPがRAIIパターンをサポートしていることを示しているようですが、PHPドキュメントでこれの検証を見つけることはできません。言語はこれをサポートしており、__destructRAIIタスクを実行するのに十分なクリーンアップロジックを配置していますか?

4

4 に答える 4

14

これは、PHPのデストラクタは予測可能ですか?とほぼ同じ質問です。答えは同じです。PHPはrefcountingを使用し、refcountがゼロになるとすぐに(通常はオブジェクトがスコープ外になると)デストラクタが呼び出されることを約束します。したがって、オブジェクトを作成し、スコープ外に漏れないように注意すれば、RAIIは実行可能です。

于 2011-02-08T21:37:51.890 に答える
5

PHPは参照カウントを使用するため、変数を使い終えるとすぐにクリーンアップされます。(サイクルを作成しない限り。)これによりリソースがすぐに解放されるため、通常、メモリサイクルを作成しないように注意する以外に、明示的なリソース管理について心配する必要はありません。

特定の戦略を実装したい場合は、リソースが1つの変数によってのみ使用されるようにすることで実装できます。その変数がリソースから離れた方向を向いている場合は常に、リソースをすぐに解放する必要があります。

于 2011-02-08T21:36:18.930 に答える
4

次のクラスは、インスタンスがスコープ外になっReturnHandlerたときにハンドラーを自動的に呼び出すことを提供します。それぞれの前にリソースを解放することを考える必要なしに、関数( )にReturnHandlerいくつかのを含めることができます。returnmyfunc

/**
 * 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);
  }
}
于 2013-03-13T13:55:08.443 に答える
0

少しオフトピック:ラムダを使用して-の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);});

完全に決定論的。そうは言っても、ラムダのterser構文はありましたか...

于 2020-11-11T18:06:59.973 に答える