Как удалить объект PHP из его класса?

Я знаю, что для некоторых это может показаться глупым, но я думал, что если у меня есть метод delete() в классе, который удаляет все данные объекта (из БД и файловой системы), как я могу уничтожить/удалить объект из класса.

это вопрос PHP. Что-то вроде unset($this); возможно ли и мудро? И как правильно это сделать?

7 ответов


при разработке на основе, я столкнулся с такой проблемой, а также. unset($this) полностью невозможно, так как $this это просто специальный указатель, который позволяет вам получить доступ к свойствам и методам текущего объекта.

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

пример RaiseFile, класс, представляющий файл:

http://code.google.com/p/phpraise/source/browse/trunk/phpraise/core/io/file/RaiseFile.php

в классе RaiseFile будет разумно, что после вызова delete() метод и файл удаляется, объект RaiseFile также должен быть удален.

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

скажем, у нас есть функция cut-paste, которая использует представление RaiseFile:

/**
 * Cut and paste a file from source to destination
 * @param string $file Pathname to source file
 * @param string $dest Pathname to destination file
 * @return RaiseFile The destination file
 */
function cutpaste($file, $dest){
    $f = new RaiseFile($file);
    $d = new RaiseFile($dest);
    $f->copy($d);
    $f->delete();
    return $d;
}

обратите внимание, как $f удаляется и GC-ed после завершения функции, потому что больше нет ссылок на RaiseFile объект $f вне функции.


вы не можете снять$this. Или правильнее:unset() on $this только локально влияет на переменную. unset() удаляет переменную из локальной области, что уменьшает количество ссылок для объекта. Если объект по-прежнему ссылается где-то еще, он останется в памяти и будет работать.

как правило, значение свойства ID используется для определения, если объект хранится в задней части. Если ID имеет правильное значение, этот объект сохраняется. Если ID null, это не хранят, пока. При успешном хранении вы затем установите ID соответственно. При удалении свойства ID устанавливается значение null снова.


Я сейчас в той же лодке.

Я создаю решение CMS с нуля и имею много ссылок между объектами; пользователи, группы, категории, форумы, темы, сообщения и т. д.

Я также использую загрузчик" Object::getObject(id) " в каждом классе, который гарантирует, что на ID есть только один экземпляр объекта, но также означает, что для кода еще проще вытащить ссылку на существующие объекты.

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

В идеале все ссылки должны быть удалены-ссылочный код может предоставить обратный вызов, который запускается при удалении объекта, который впоследствии может удалить/обновить ссылку. Но если ссылочный код становится небрежным, я бы предпочел ошибку с ошибкой "не объект", чем фактически работать с объектом.

без зная, как заставить разрушение изнутри самого объекта, я вынужден:

  1. начните почти каждый нестатический метод с проверки, чтобы увидеть, был ли объект помечен "удален", создавая исключение, если это так. Это гарантирует, что любой ссылочный код не может причинить никакого вреда, но это неприятная вещь, чтобы посмотреть в коде.

  2. снимите все объектные переменные после удаления из базы данных, чтобы они не задерживались в памяти. Не большой дело, но, опять же: неприятно смотреть.

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


Это зависит от того, как вы структурировали класс.

Если вы следуете шаблонам DTO/DAO, ваши данные будут отделены от вашей модели, и вы можете просто удалить DTO. Если это не так, просто сбросить данные часть класса должна сделать это.

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


есть _ _ destruct () magic метод, который является деструктором для класса PHP.

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


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


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

объект не может просто волшебным образом исчезнуть - он будет удален (собран мусор) только тогда, когда на него ничего не указывает. Поэтому" все", что должен делать объект, - это отслеживать все, что относится к нему. Это довольно низкое трение, когда у вас есть все ссылки, встроенные в объекты создаются и передаются только фиксированных методов.

давайте начнем с простого интерфейса, чтобы мы могли сказать, безопасно ли передавать нашу ссылку на объект или нет.

interface removableChildInterface
{

    public function removeChild($obj);

}

класс, который может безопасно хранить ссылку на наш объект.

class MyParent implements removableChildInterface
{

    public $children = array();

    public function removeChild($child)
    {
        $key = array_search($child, $this->children);
        unset($this->children[$key]);
    }

}

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

class Suicidal
{

    private $parents = array(); // Store all the reference holders
    private $id; // For example only
    private $memory = ''; // For example only
    public static $counter = 0; // For example only

    public function __construct(&$parent)
    {
        // Store a parent on creation
        $this->getReference($parent);
        // For the example lets assing an id
        $this->id = 'id_' . ++self::$counter;
        // and generate some weight for the object.
        for ($i = 0; $i < 100000; $i++) {
            $this->memory .= md5(mt_rand() . $i . self::$counter);
        }
    }

    // A method to use for passing the object around after its creation.
    public function getReference(&$parent)
    {
        if (!in_array($parent, $this->parents)) {
            $this->parents[] = &$parent;
        }
        return $this;
    }

    // Calling this method will start the removal of references to this object.
    // And yes - I am not actually going to call this method from within this
    // object in the example but the end result is the same.
    public function selfDestruct()
    {
        foreach ($this->parents as &$parent) {
            if (is_array($parent)) {
                $key = array_search($this, $parent);
                unset($parent[$key]);
                echo 'removing ' . $this->id . ' from an array<br>';
            } elseif ($parent instanceof removableChildInterface) {
                $parent->removeChild($this);
                echo 'removing ' . $this->id . ' from an object<br>';
            }
            // else throw your favourite exception
        }
    }

    // A final shout out right before being garbage collected.
    public function __destruct()
    {
        echo 'destroying ' . $this->id . '<br>';
    }

}

и для примера использования, удерживая ссылку в array, в object реализуя наши interface и $GLOBALS array.

// Define collectors
$array = array();
$parent = new MyParent();

// Store objects directly in array
$array['c1'] = new Suicidal($array);
$array['c2'] = new Suicidal($array);

// Make a global reference and store in object
$global_refrence = $array['c1']->getReference($GLOBALS);
$parent->children[] = $array['c1']->getReference($parent);

// Display some numbers and blow up an object.
echo 'memory usage with 2 items ' . memory_get_usage() . ' bytes<br>';
$array['c1']->selfDestruct();
echo 'memory usage with 1 item ' . memory_get_usage() . ' bytes<br>';

// Second object is GC-d the natural way after this line
echo '---- before eof ----' . '<br>';

выход:

memory usage with 2 items 6620672 bytes
removing id_1 from an array
removing id_1 from an array
removing id_1 from an object
destroying id_1
memory usage with 1 item 3419832 bytes
---- before eof ----
destroying id_2