Поддерживает ли PHP шаблон RAII?Как? - PullRequest
11 голосов
/ 09 февраля 2011

Большинство ресурсов PHP никогда не касаются управления памятью, потому что сам язык довольно хорош для этого. Однако в PHP вы часто сталкиваетесь с внешними ресурсами, которые не являются памятью - дескрипторами базы данных, сеансами, транзакциями базы данных и т. Д. Этими внешними ресурсами можно было бы управлять наиболее чисто, используя некоторую форму объекта RAII.

Сначала я думал, что PHP использует схему сбора мусора, аналогичную JVM или CLR, где концепция деструктора не существует. (Помните: Каждый думает о сборке мусора неправильно - финализаторы не являются деструкторами!) Есть специальный метод __destruct, но я подумал, что это был "финализатор", похожий на финализатор Java или C #. По этой причине вы не можете использовать RAII на JVM или CLR (блоки C # using позволяют получить около 95% пути, но это немного по-другому ...).

Однако, Google, похоже, указывает, что PHP поддерживает шаблон RAII , хотя я не могу найти подтверждение этого в документации по PHP. Поддерживает ли язык это и помещает логику очистки в __destruct, достаточную для выполнения задач RAII?

Ответы [ 3 ]

11 голосов
/ 09 февраля 2011

Это почти тот же вопрос, что и Является ли деструктор в PHP предсказуемым? и ответ тот же.PHP использует refcounting и обещает, что деструктор будет вызван немедленно, как только refcount достигнет нуля (как правило, когда объект выходит из области видимости).Поэтому, если вы создаете объект и стараетесь не вывести его из области видимости, RAII является жизнеспособным.

4 голосов
/ 09 февраля 2011

PHP использует подсчет ссылок, поэтому, когда вы закончите работу с переменной, он будет немедленно очищен.(Если вы не создаете циклы.) Это освобождает ресурсы быстро, поэтому вам, как правило, не нужно беспокоиться о явном управлении ресурсами, кроме того, чтобы не создавать циклы памяти.

Если вы действительно хотите реализовать какую-то конкретную стратегию,Вы можете сделать это, убедившись, что ресурс используется только одной переменной.Всякий раз, когда эта переменная указывается в стороне от ресурса, ресурс должен быть немедленно освобожден.

2 голосов
/ 13 марта 2013

Следующий класс 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);
  }
}
...