Разрушители Php

Пожалуйста, дайте мне примеры реальной жизни, когда вам приходилось использовать __destruct в своих классах.

Хорошо, так как мой последний ответ, по-видимому, не попал в цель, позвольте мне попробовать это снова. В этой теме есть много ресурсов и примеров в Интернете. Выполняя немного поиска и просмотра кода другой фреймворка, вы увидите несколько хороших примеров …

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

Теперь мы знаем, что __destruct вызывается, когда объект уничтожается. Логически, что произойдет, если объект будет уничтожен? Ну, это означает, что он больше не доступен. Итак, если у него открыты ресурсы, разве нет смысла закрывать эти ресурсы, поскольку они уничтожаются? Конечно, на средней веб-странице страница скоро закончится, поэтому закрытие PHP обычно не страшно. Однако что произойдет, если по какой-то причине сценарий длительный? Тогда у вас есть утечка ресурсов. Так почему бы просто не закрыть все, когда вам это больше не нужно (или учитывая объем деструктора, когда он больше не доступен)?

Вот несколько примеров в реальном мире:

  1. Литиевый литий \ net \ Socket class
  2. Мембранный драйвер Kohana
  3. Реализация FTP Joomla
  4. Zend Frameworks SMTP Mail Transport Class
  5. Класс TTemplate CodeIgniter
  6. Помощник фильтра Tidy для торта
  7. Тема Google-Groups об использовании деструкторов для класса сеанса Symfony

Интересно то, что Kohana отслеживает теги, чтобы впоследствии удалять их через «пространство имен» (а не просто очищать кеш). Поэтому он использует деструктор, чтобы скрыть эти изменения в жестком хранилище.

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

Я лично использую деструкторы, когда у меня есть длительные процессы на моем главном контроллере. В конструкторе я проверяю файл pid . Если этот файл существует (и его процесс все еще запущен), я генерирую исключение. Если нет, я создаю файл с текущим идентификатором процессов. Затем в деструкторе я удаляю этот файл. Так что это больше об очистке после себя, чем просто освобождении ресурсов …

Существует еще одно удобное использование для создания HTML-страницы

 class HTMLgenerator { function __construct() { echo "<html><body>"; } function __destruct() { echo "</body></html>"; } } 

С помощью этого класса вы можете написать

 $html = new HTMLgenerator(); echo "Hello, world!"; 

И результат

 <html><body>Hello, world!</body></html> 

Например:

 <?php class Session { protected $data = array(); public function __construct() { // load session data from database or file } // get and set functions public function __destruct() { // store session data in database or file } }; 

Это полезно использовать деструкцию. Вы запрещаете чтение и запись на источник сеанса все время и делаете это только в начале и в конце.

Я создаю страницу php, которая будет генерировать файл jpg информации о фильме. Эта страница должна будет собрать несколько информации и запустить inkscape для преобразования шаблона (файл svg) в png перед преобразованием в jpg. SVG содержит относительные ссылки на другое изображение, которое должно быть файлом. Поэтому моя страница загружает необходимые файлы во временную папку, конвертирует SVG-файл. В конце временная папка должна быть удалена.

Я помещаю временную папку в деструктор. Прежде чем может быть много причин, страница неожиданно заканчивается, и единственное, что я могу быть уверенным в том, что деструктор будет вызываться при выходе страницы.

Надеюсь это поможет.

Деструктор чрезвычайно полезен, если вы используете специальный соединитель / оболочку базы данных.

В конструкторе вы можете передать информацию о соединении. Поскольку вы можете использовать деструктор (а не финализатор и т. Д.), Вы можете положиться на это, чтобы закрыть соединение для вас. Это более удобно, но это, безусловно, полезно.

Например, когда PHP решает явно «освободить» объект (т. Е. Он больше не используется), он вызовет деструктор в это время. Это более полезно в описываемом сценарии, поскольку вы не ожидаете запуска сборщика мусора и вызываете финализатор.

$ 0,02

Ян

 <?php class Database { private $connection; private $cache = array(); function __construct([$params]) { //Connection here } //Query public function query(Query $Query) { if($this->is_cached($Query->checksum)) { return $this->get_cache($Query->checksum); } //... } public function __destruct() { unset($this->connection); $this->WriteCache(); unset($this->cache); shutdown_log($this,'Destruction Completed'); } } ?> с <?php class Database { private $connection; private $cache = array(); function __construct([$params]) { //Connection here } //Query public function query(Query $Query) { if($this->is_cached($Query->checksum)) { return $this->get_cache($Query->checksum); } //... } public function __destruct() { unset($this->connection); $this->WriteCache(); unset($this->cache); shutdown_log($this,'Destruction Completed'); } } ?> с <?php class Database { private $connection; private $cache = array(); function __construct([$params]) { //Connection here } //Query public function query(Query $Query) { if($this->is_cached($Query->checksum)) { return $this->get_cache($Query->checksum); } //... } public function __destruct() { unset($this->connection); $this->WriteCache(); unset($this->cache); shutdown_log($this,'Destruction Completed'); } } ?> 

это пример, который должен вас понять.

Если вы используете дескрипторы, возвращаемые fopen() скажем, для ведения журнала, вы можете использовать __destruct() чтобы удостовериться, что fclose() вызывается в наших ресурсах, когда ваш класс уничтожен.

Вы правы, __destruct в большинстве случаев не нужен для коротких сценариев php. Соединения с базами данных, дескрипторы файлов и т. Д. Закрываются при выходе сценария или иногда даже раньше, если переменные заканчиваются.

Одним из примеров, о которых я могу думать, является запись журналов в базу данных. Поскольку мы не хотели запускать один запрос на запись в журнале, который создается где-то в сценарии, мы написали часть «write to db» в __destruct класса ведения журнала, поэтому, когда скрипт заканчивается, все вставляется в базу данных на одном.

Другой пример: если вы разрешаете пользователю загружать файлы, деструктор иногда является хорошим местом для удаления временного файла (в случае, если в сценарии что-то не так, по крайней мере, оно очищается)

Но даже для дескрипторов файлов это может быть полезно. Я работал над приложением, которое использовало старые вызовы fopen и т. Д., Обернутые в объекты, и при использовании тех, на больших файловых файлах php рано или поздно закончится файловыми дескрипторами, поэтому очистка во время работы скрипта была не только приятной, но и необходимой ,

Я использую кэширование APC для большого количества объектов с низким уровнем, которые в противном случае использовали бы чрезмерную память; и у меня есть объект cacheCollection, который обрабатывает чтение и запись этих объектов «низкого уровня» в APC и из APC во время выполнения скрипта. Когда сценарий завершается, объекты должны быть очищены от APC, поэтому я использую метод cacheCollection __destruct для выполнения этой функции.

Я использовал __destruct() в классе журнала, который завершил соединение с базой данных:

 <?php class anyWrap { private $obj,$calls,$log,$hooks; function anyWrap($obj, $logfile = NULL) { if(is_null($logfile)) { $this->log = dirname(__FILE__) . "/../logs/wrapLog.txt"; } $this->hooks = array(); $this->dbCalls = 0; $this->obj = $obj; } public function __set($attri, $val) { $this->obj->$attri = $val; } public function __get($attri) { return $this->obj->$attri; } public function __hook($method) { $this->hooks[] = $method; } public function __call($name,$args) { $this->calls++; if(in_array($name,$this->hooks)) { file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND); } return call_user_func_array(array($this->obj,$name),$args); } //On destruction log diagnostics public function __destruct() { unset($this->dbReal); file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND); } } с <?php class anyWrap { private $obj,$calls,$log,$hooks; function anyWrap($obj, $logfile = NULL) { if(is_null($logfile)) { $this->log = dirname(__FILE__) . "/../logs/wrapLog.txt"; } $this->hooks = array(); $this->dbCalls = 0; $this->obj = $obj; } public function __set($attri, $val) { $this->obj->$attri = $val; } public function __get($attri) { return $this->obj->$attri; } public function __hook($method) { $this->hooks[] = $method; } public function __call($name,$args) { $this->calls++; if(in_array($name,$this->hooks)) { file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND); } return call_user_func_array(array($this->obj,$name),$args); } //On destruction log diagnostics public function __destruct() { unset($this->dbReal); file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND); } } 

Сценарий перехватывает вызовы базы данных и записывает в них команды подготовки, а затем, когда сценарий заканчивается (я не всегда знаю, когда), он, наконец, регистрирует количество вызовов в базе данных в файл. Таким образом, я вижу, сколько раз определенные функции вызывались в базе данных и соответственно планировали мою оптимизацию.

Если вы создаете представление с использованием PHP-скрипта в базе данных MySQL , вы должны отказаться от этого представления в конце скрипта. Потому что, если нет, то в следующий раз, когда сценарий будет выполнен, представление не будет создано, так как в базе данных уже есть аналогичное имя. Для этого вы можете использовать деструктор.