取消设置对象PHP的所有实例

时间:2014-01-10 07:28:46

标签: php object unset

我有一个类,它返回一个自身的新实例。 这允许我使用一个单独的对象,而不必使用相同的值反复声明新的对象。对于那些想要为什么不扩展课程或其他东西的人来说,它只是让我的生活更轻松,它就像一个魅力,但我的最终目的是将它们全部删除。

例如:

$foo = new myClass('name1','ab','cd');
$bar = $foo->duplicate();

//duplicate() saves the new object in itself in an array:
array_push($this->instance,new myClass('name1','ab','cd'));
//and returns a pointer to the saved instance.
return end($this->instance);

$foo$bar现在共享相同的方法和值,但这些值可以单独修改。

$foo->changeName('newName'); 

$bar->changeName('newName2');

我的问题是,如果我取消设置创建的第一个类unset($foo),PHP会自动取消设置其他实例($bar)还是垃圾收集器最终会删除它们?

我通过解决$ foo来测试它并在我调用$ foo时给出了一个错误,但是当我调用$ bar时却没有。

我要做的是立即取消设置该类的所有实例。

感谢。

3 个答案:

答案 0 :(得分:3)

自动清理?

不,PHP不了解您的架构。它不会删除对象“级联”,它们是独立的实体 - 而且,更多,可以属于不同的范围,例如。简单的代码:

class Test
{
   protected $id = null;
   protected $uniqid = null;

   public function __construct($id)
   {
      $this->id = $id;//user-passed variable
      $this->uniqid = uniqid();//internal: to identify instance 
   }

   public function getCopy()
   {
      return new self($this->id);
   }

   public function getIdentity()
   {
      return $this->uniqid;
   }
}

$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity());//valid

unset($foo);
//still valid: bar has nothing to do with foo
var_dump($bar->getIdentity());

顺便说一句,对于复制,您可以在PHP中使用clone(但是,这会导致对象克隆,显然)

简单方法

解决问题的最简单方法是迭代$GLOBALS,并使用instanceof进行检查。这有一个严重的缺点:内部函数/方法范围不会受到影响:

//static since doesn't belong to any instance:
public static function cleanup()
{
   foreach($GLOBALS as $name=>$var)
   {
      if($var instanceof self)
      {
         unset($GLOBALS[$name]);
      }
   }
}

- 和

$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity(), $bar->getIdentity());//valid
Test::cleanup();
//2 x notice:
var_dump($foo, $bar);

注意,这与“子”机制无关(即它将清除全局范围内的所有实例 - 无论从哪个实例复制)。

常见案例

以上示例执行常见情况下的操作。为什么?想象一下,你将拥有持有人类:

class Holder
{
   protected $obj = null;

   public function __construct($obj)
   {
      $this->obj = $obj;
   }

   public function getData()
   {
      return $this->obj;
   }
}

你会将实例传递给它:

$foo = new Test(3);
$bar = $foo->getCopy();
$baz = new Holder($bar);

- 那么在普通情况下你甚至没有机会处理这种简单的情况。在更复杂的情况下,你也会陷入困境。

怎么做?

我建议:在需要时明确地销毁对象。隐式unset是一个副作用,即使你会以某种方式维护(我可以想象Observer模式+一些全局注册表) - 这将是可怕的副作用,这会破坏你的代码的可读性。关于使用上面我写过的$GLOBALS的代码也一样 - 我不建议在任何情况下采取这种方式。

答案 1 :(得分:0)

根据我在PHP参考中的理解:

http://www.php.net/manual/en/features.gc.refcounting-basics.php

销毁主实例不会自动销毁所有其他实例,因为它们最终不会指向相同的'zval'。

但是,如果不再引用垃圾收集,垃圾收集最终将销毁所有实例。因为在你的例子中,$ bar仍然引用第二个实例,所以它不会被销毁。

如果你想同时取消所有这些,你可以做什么:

  1. 使用引用对象的所有实例的静态数组
  2. 每次创建新对象时,在类
  3. 的静态数组中添加对此对象的引用
  4. 使用静态函数unsetAll()循环遍历此数组并逐个取消设置所有实例

答案 2 :(得分:0)

尝试使用以下代码清除所有php对象。

public function clearAllVars() 
   { 
      $vars = get_object_vars($this); 
      foreach($vars as $key => $val) 
      { 
         $this->$key = null; 
      } 
   } 
}