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

У меня следующая проблема. Я использую класс, и я хочу сделать некоторое «сохранение (и ведение журнала) событий» в методе __destructor, мне нужно быть уверенным, что мой класс базы данных все еще активен, и даже что мой класс memcache все еще активен.

Я заметил, что метод деструктора может быть вызван слишком поздно. (класс базы данных больше не активен, класс memcache больше не активен)

Обходной путь, который я нашел, это...

$forum = new Forum_class();
$forum->output();
unset($forum) <-- unset it

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

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

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

Изменить: кажется, я наткнулся на эту ошибку https://bugs.php.net/bug.php?id=39381. Мой класс базы данных и класс memcache используют глобальные переменные...


person Milio    schedule 14.07.2012    source источник
comment
Вы можете изучить register_shutdown_function().   -  person nickb    schedule 14.07.2012
comment
Чем больше я читаю там, тем больше я думаю, что я просто не должен полагаться на метод __destructor для выполнения сложных вещей... Я не могу просто зарегистрировать свой метод __destruct как функцию завершения работы, иначе он будет вызываться дважды. Что бы вы там зарегистрировали? И что бы это решило?   -  person Milio    schedule 14.07.2012


Ответы (2)


Вы делаете это правильно. Но...

Деструктор МОЖЕТ быть вызван после уничтожения последней ссылки на объект. Даже unset($object) не гарантирует, что деструктор будет вызван сразу после unset().

$forum = new Forum_class();
$forum->output();
$forumCopy = $forum;
unset($forum); // php doesnt even consider calling the destructor
unset($forumCopy); // now the destructor is going to be called... in some time
person Sergey Eremin    schedule 14.07.2012
comment
Имеет смысл, но что вы имеете в виду под... через какое-то время... Если моя функция выключения просто печатает "у.е. позже", а следующая строка в моем коде печатает "мой друг"... Разве не безопасно ожидать 'у.е. позже, мой друг' в качестве вывода? (Это означает, что метод деструктора вызывается, как только вы действительно отключаете класс... Или я что-то упустил? - person Milio; 14.07.2012
comment
Я имею в виду, что деструктор будет вызываться между моментом уничтожения последней ссылки и моментом завершения скрипта. У разработчика нет возможности контролировать или угадывать момент вызова деструктора. Если вы сбрасываете несколько экземпляров, их деструкторы могут вызываться не в том порядке, в котором они были сброшены. - person Sergey Eremin; 14.07.2012

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

В принципе, хотя вы можете попробовать гибридный подход:

class Foo
{
  protected $resource;

  public function close()
  {
    if ($this->resource)
    {
      $this->resource->foo();
      $this->resource = null;
    }  
  }

  public function __destruct()
  {
    $this->close();
  }
}

Таким образом, вы можете явно «закрыть» свой ресурс, но также лениво сделать это через деструктор на всякий случай.

Если очистка (метод close()) критична, то я бы изменил метод __destruct, чтобы записывать в файл (например, вызывать уведомление), если он не был очищен. Таким образом, вы могли бы легко найти и исправить эти проблемы.

person Matthew    schedule 14.07.2012