Php Destructors

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

63
задан tereško 12 July 2014 в 07:54
поделиться

11 ответов

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

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

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

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

  1. Класс литий\net\Socket в Lithium
  2. ​​Драйвер Memcached от Kohana
  3. Реализация FTP для Joomla
  4. Класс почтового транспорта SMTP от Zend Frameworks
  5. Класс TTemplate от CodeIgniter
  6. Удобный вспомогательный фильтр для Cake
  7. Тема Google-Groups об использовании деструкторов для сеанса Symfony Класс

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

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

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

43
ответ дан 24 November 2019 в 16:25
поделиться

Например:

<?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
    }
};

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

6
ответ дан 24 November 2019 в 16:25
поделиться
<?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');
    }
}
?>

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

4
ответ дан 24 November 2019 в 16:25
поделиться

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

4
ответ дан 24 November 2019 в 16:25
поделиться

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

3
ответ дан 24 November 2019 в 16:25
поделиться

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

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

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

$0.02

Ян

4
ответ дан 24 November 2019 в 16:25
поделиться

Есть еще одно удобное применение для создания 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>
19
ответ дан 24 November 2019 в 16:25
поделиться

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

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

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

4
ответ дан 24 November 2019 в 16:25
поделиться

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

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

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

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

4
ответ дан 24 November 2019 в 16:25
поделиться

Я использовал __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);
   }
}

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

2
ответ дан 24 November 2019 в 16:25
поделиться

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

1
ответ дан 24 November 2019 в 16:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: