I seem to recall a way to setup the __destruct
for a class in such a way that it would ensure that circular references would be cleaned up as soon as the outside object falls out of scope. However, the simple test I built seems to indicate that this is not behaving as I had expected/hoped.
Is there a way to setup my classes in such a way that PHP would clean them up correctly when the outermost object falls out of scope?
I am not looking for alternate ways to write this code, I am looking for whether or not this can be done, and if so, how? I generally try to avoid these types of circular references where possible.
class Bar {
private $foo;
public function __construct($foo) {
$this->foo = $foo;
}
public function __destruct() {
print "[destroying bar]\n";
unset($this->foo);
}
}
class Foo {
private $bar;
public function __construct() {
$this->bar = new Bar($this);
}
public function __destruct() {
print "[destroying foo]\n";
unset($this->bar);
}
}
function testGarbageCollection() {
$foo = new Foo();
}
for ( $i = 0; $i < 25; $i++ ) {
echo memory_get_usage() . "\n";
testGarbageCollection();
}
The output looks like this:
60440
61504
62036
62564
63092
63620
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
What I had hoped for:
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
UPDATE:
There are several great answers to this question relating to PHP > 5.3, but I selected the answer that would work with PHP < 5.3 since it actually relates to my project ( PHP 5.2.x ).