繁体   English   中英

如何从类中删除PHP对象?

[英]How to delete a PHP object from its class?

我知道对于一些可能听起来很愚蠢的人,但我在想如果我在一个删除所有对象数据(来自DB和文件系统)的类中有一个delete()方法,我怎么能从内部销毁/删除对象类。

这是一个PHP问题。 像未unset($this);东西unset($this); 有可能吗?明智吗? 什么是正确的方法呢?

在开发框架的同时,我也遇到了这样的问题。 unset($this)完全不可能,因为$this只是一个特殊的指针,允许您访问当前对象的属性和方法。

唯一的方法是在方法/函数中封装对象的使用,这样当方法/函数结束时,对对象的引用就会丢失,垃圾收集器会自动释放内存以用于其他事情。

请参阅示例RaiseFile ,一个表示文件的类:

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

在RaiseFile类中,在调用delete()方法并删除文件之后,还应该删除RaiseFile对象是明智的。

但是,由于您提到的问题,我实际上必须坚持RaiseFile指向文件,无论文件是否存在。 可以通过exists()方法跟踪文件的exists()

假设我们有一个使用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,因为$f外部没有更多对RaiseFile对象$f引用。

你不能取消$this 或者更正确: $this unset()上的unset()只对变量有局部影响。 unset()从本地范围中删除变量,这会减少对象的引用计数。 如果对象仍在其他地方引用,它将保留在内存中并工作。

通常,ID属性的值用于确定对象是否存储在后端。 如果ID具有适当的值,则存储该对象。 如果ID为null ,则尚未存储。 成功存储后,您可以相应地设置ID。 在删除时,您再次将ID属性设置为null

我现在在同一条船上。

我正在从头开始构建CMS解决方案,并在对象之间有很多引用; 用户,群组,类别,论坛,主题,帖子等

我还在每个类中使用“Object :: getObject(id)”加载器,确保每个ID只有一个对象实例,但也意味着代码更容易提取对现有对象的引用。

当对象表示的数据从数据源中删除时,我想从内存中擦除对象并取消对它的所有引用,以确保其他代码不会尝试使用过时的数据集。

理想情况下,应删除所有引用 - 引用代码可以提供在删除对象时触发的回调,随后可以删除/更新引用。 但是如果引用代码变得草率,我宁愿错误地使用“Not an object”错误而不是实际使用该对象。

在不知道如何强迫对象内部进行破坏的情况下,我被迫:

  1. 开始几乎所有非静态方法,检查对象是否已被标记为“已删除”,如果是,则抛出异常。 这可以确保任何引用代码都不会造成任何伤害,但在代码中查看它是一件令人讨厌的事情。

  2. 从数据库中删除后取消设置每个对象变量,因此它不会留在内存中。 没什么大不了的,但是,再次:讨厌看。

如果我可以从内部破坏物体,那么也不需要。

这是一个示例解决方案,当以明确定义的关系/参考模式实现时,它将“合理地可用”,通常我在我的复合材料中放弃这样的东西。 实际上使用当前代码就像我在现实生活中所做的那样,会遇到太多麻烦,但这只是为了说明如何进行操作。

一个对象不能只是神奇地消失 - 一旦没有任何指向它就会被删除(垃圾收集)。 所以一个对象必须要做的就是跟踪引用它的所有内容。 当你内置了所有的引用管理时,它的摩擦力相当低 - 只能通过固定的方法创建和传递对象。

让我们从一个简单的接口开始,这样我们就可以判断是否可以安全地传递对象的引用。

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 ,在实现我们的interfaceobject$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

这取决于你的课程结构。

如果您遵循DTO / DAO模式,您的数据将与您的模型分开,您只需删除DTO即可。 如果不是,只需取消设置类的数据部分即可。

但实际上,我认为这是不必要的,因为PHP会在请求结束时自动清理。 除非你正在处理一个占用大量内存的巨大物体,而且这是一个漫长的过程,所以这并不值得付出努力。

有一个__destruct()魔术方法,它是PHP类的析构函数。

也许您可以将删除代码放在那里,只要删除对所有对象的引用,就会调用此析构函数并删除数据。

另一种方法是使delete-method静态,然后可以接收PDO对象和数据,确定要删除的内容。 这样您就不需要初始化对象了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM