我知道对于一些可能听起来很愚蠢的人,但我在想如果我在一个删除所有对象数据(来自DB和文件系统)的类中有一个delete()方法,我该如何销毁/删除对象来自班上。
这是一个PHP问题。像unset($this);
这样的事情是否可行且明智?什么是正确的方法呢?
答案 0 :(得分:6)
虽然在框架上进行开发,但我也遇到了这样的问题。 unset($this)
完全不可能,因为$this
只是一个特殊的指针,允许您访问当前对象的属性和方法。
唯一的方法是封装在方法/函数中使用对象,这样当方法/函数结束时,对象的引用就会丢失,垃圾收集器会自动释放内存以供其他的东西。
参见示例RaiseFile
,一个代表文件的类:
http://code.google.com/p/phpraise/source/browse/trunk/phpraise/core/io/file/RaiseFile.php
在RaiseFile类中,在调用delete()
method并删除文件后,也应该删除RaiseFile对象,这是明智的。
然而,由于您提到的问题,我实际上必须坚持RaiseFile指向文件,无论该文件是否存在。可以通过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,因为函数外部没有对RaiseFile
对象$f
的引用。
答案 1 :(得分:3)
你不能取消$this
。或者更准确:unset()
$this
仅对变量产生局部影响。 unset()
从本地范围中删除变量,这会减少对象的引用计数。如果对象仍在其他地方被引用,它将保留在内存中并起作用。
通常,ID属性的值用于确定对象是否存储在后端。如果ID具有适当的值,则存储该对象。如果ID为null
,则尚未存储。成功存储后,您可以相应地设置ID。在删除时,您再次将ID属性设置为null
。
答案 2 :(得分:1)
我现在在同一条船上。
我正在从头开始构建CMS解决方案,并且在对象之间有很多引用;用户,群组,类别,论坛,主题,帖子等。
我还在每个类中使用“Object :: getObject(id)”加载器,确保每个ID只有一个对象实例,但也意味着代码更容易提取对现有对象的引用。
当对象表示的数据从数据源中删除时,我想从内存中擦除对象并取消对它的所有引用,以确保其他代码不会尝试使用过时的数据集。
理想情况下,应删除所有引用 - 引用代码可以提供在删除对象时触发的回调,随后可以删除/更新引用。但是如果引用代码变得草率,我宁愿错误地使用“Not an object”错误而不是实际使用该对象。
在不知道如何强迫对象内部进行破坏的情况下,我被迫:
开始几乎所有非静态方法,检查对象是否已被标记为“已删除”,如果是,则抛出异常。这可以确保任何引用代码都不会造成任何伤害,但在代码中查看它是件令人讨厌的事情。
从数据库中删除后取消设置每个对象变量,因此它不会留在内存中。不是什么大不了的事,但又是:讨厌看。
如果我可以从内部摧毁对象,那么也不需要。
答案 3 :(得分:0)
这取决于你的课程结构。
如果您遵循DTO / DAO模式,您的数据将与您的模型分开,您只需删除DTO即可。如果不是,只需取消设置类的数据部分即可。
但实际上,我认为这是不必要的,因为PHP会在请求结束时自动清理。除非你正在处理一个占用大量内存的巨大物体,而且这是一个漫长的过程,所以这并不值得付出努力。
答案 4 :(得分:0)
有一个__destruct()魔术方法,它是PHP类的析构函数。
也许您可以将删除代码放在那里,只要删除对对象的所有引用,就会调用此析构函数并删除数据。
答案 5 :(得分:0)
另一种方法是使delete-method静态,然后可以接收PDO对象和数据,确定要删除的内容。这样您就不需要初始化对象了。
答案 6 :(得分:0)
这是一个示例解决方案,当以明确定义的关系/参考模式实现时,它将是“合理可用的”,通常我会在我的复合中丢弃这样的东西。实际上使用当前代码就像我在现实生活中所做的那样,会遇到太多麻烦,但这只是为了说明如何进行操作。
一个对象不能只是神奇地消失 - 一旦没有任何指向它就会被删除(垃圾收集)。所以一个对象必须要做的就是跟踪引用它的所有内容。当你内置了所有的引用管理时,它的摩擦力相当低 - 只能通过固定的方法创建和传递对象。
让我们从一个简单的界面开始,这样我们就可以判断是否可以安全地传递对象的引用。
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