Reputation: 9696
I have a class with a method that returns a new instance of itself. This allows me to use one single object without having to declare new ones over and over with the same values. For those wondering why not extending the class or something else, it just makes my life easier and it works like a charm, but my final purpose is to remove them all in one line.
for example:
$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
and $bar
now share the same methods and values but those values can be modified separately.
$foo->changeName('newName');
$bar->changeName('newName2');
My question here is, if I unset the first class created unset($foo)
will PHP automatically unset the other instances ($bar)
or will the garbage collector remove them eventually?
I have tested it by unsettling $foo and gives me an error when I call $foo but not when I call $bar.
What I am trying to do is to unset all the instances of that class at once.
Thanks.
Upvotes: 4
Views: 2864
Reputation: 76
From what I understand from the PHP reference here :
http://www.php.net/manual/en/features.gc.refcounting-basics.php
destroying the main instance will not automatically destroy all other instances since they do not ultimately point to the same 'zval'.
However the garbage collection will eventually destroy all instances if they are not referenced anymore. Since in your example $bar still references the second instance, it will not be destroyed.
What you could do if you want to unset them all at the same time :
Upvotes: 0
Reputation: 37365
Automatic cleanup?
No, PHP isn't awared about your architecture. It will not remove objects "cascade", they are independent entities - and, more, can belong to different scopes, for example. Simple code:
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());
By the way, for copying you can use clone
in PHP (that, however, will result in object cloning, obviously)
Simple way
Most simple way to resolve a matter is to iterate through $GLOBALS
, checking it with instanceof
. This has serious weakness: inner function/method scopes would not be affected:
//static since doesn't belong to any instance:
public static function cleanup()
{
foreach($GLOBALS as $name=>$var)
{
if($var instanceof self)
{
unset($GLOBALS[$name]);
}
}
}
-and
$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity(), $bar->getIdentity());//valid
Test::cleanup();
//2 x notice:
var_dump($foo, $bar);
Note, that is has nothing to do with "child" mechanics (i.e. it will clean all instances in global scope - no matter which was copied from which).
Common case
Sample above will not do the stuff in common case. Why? Imagine that you'll have holder class:
class Holder
{
protected $obj = null;
public function __construct($obj)
{
$this->obj = $obj;
}
public function getData()
{
return $this->obj;
}
}
and you'll pass instance to it:
$foo = new Test(3);
$bar = $foo->getCopy();
$baz = new Holder($bar);
-so then you'll have no chances to handle even this simple situation in common case. And with more complex situations you will also be stuck.
What to do?
I'd recommend: destroy objects explicitly when you need to do that. Implicit unset is a side-effect, and even if you'll maintain that somehow (I can imagine Observer pattern + some global registry for that) - it will be horrible side-effect, that will kill readability for your code. And same is about code, that uses $GLOBALS
I've written above - I do not recommend to act such way in any case.
Upvotes: 3
Reputation: 1
Try the below code to clear all php objects.
public function clearAllVars()
{
$vars = get_object_vars($this);
foreach($vars as $key => $val)
{
$this->$key = null;
}
}
}
Upvotes: 0