__destruct() order

admin

Administrator
Staff member
I am a bit confused about the order how the objects are destructed in PHP 5.0.3. The doc says The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed. But the following example <?php
class UtilityClass {
private $myID = 123;
public function __construct ( ) {
echo "UtilityClass($this->myID).__construct()<br>";
}
public function __destruct ( ) {
echo "UtilityClass($this->myID).__destruct()<br>";
}
public function printOut ( $outValue ) {
echo "UtilityClass($this->myID).printOut ($outValue)<br>";
}
} // Utility Class

class TaskClass {
private $utilityObj;
public function __construct ( $UtilityClassObject ) {
echo "TaskClass.__construct(" . get_class($UtilityClassObject) . ")<br>"
;
$this->utilityObj = $UtilityClassObject;
}
public function __destruct ( ) {
echo "TaskClass.__destruct()<br>";
$this->utilityObj->printOut ("are you still there?");
}
public function doWork ( ) {
$this->utilityObj->printOut ("Work is done.");
}
} // TaskClass

$utility = new UtilityClass ( );
$task = new TaskClass ( $utility );

$task->doWork ( );

?>producesUtilityClass(123).__construct()
TaskClass.__construct(UtilityClass)
UtilityClass(123).printOut (Work is done.)
UtilityClass(123).__destruct()
TaskClass.__destruct()
UtilityClass(123).printOut (are you still there?)From my opinion, not all references to UtilityClass are removed and still its __destruct method is called before TaskClass's __destruct method.

But maybe I am worrying for nothing, since the UtilityClass seems to be still there ? How to explicitly destroy an object ?

CanneIt's at least partly to do with the fact that this is occurring at the end of the script. Normal reference counting rules are held in abeyance; partly for efficiency reasons and partly because otherwise the cleanup process could get stuck on things like circular references. When the script terminates, the internal object list is just cranked through from beginning to end, calling all of the destructors found; the objects are retained though, in case there are other objects whose destructors are still to be called that are referring to them. This is quicker and more effective than chasing references, and any transient problems caused by objects still sitting around after they're destroyed goes unnoticed, because the program state is just as consistent afterwards as it was beforehand - only now all the objects are gone. But that's okay, because everything else is gone as well.

To explicitly remove a (reference to) an object, $object = null; or unset($object); . Consider

$utility = new UtilityClass ( );
$task = new TaskClass ( $utility );
$task->doWork ( );
$task = null;
echo '$utility is still around.';

and
$utility = new UtilityClass ( );
$task = new TaskClass ( $utility );
$utility = null;
$task->doWork ( );
$task = null;
echo 'All gone!';

In short, word from Andi Guttmans is A VERY important implication is that you cannot, and must not rely in any way on the order of destruction during shutdown. It runs in no particular order. That means that by the time the destructor for your object $foo is called, a reference to some other object $bar may already be post-destruction. Note that it will still be 鎱絥tact?and accessible in the sense that if you access it - there won鎶
 
Top