|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2011-01-08 15:59 UTC] hausner15 at gmail dot com
Description:
------------
I think, in this example after destructor executing, object shouldn`t exist. But result of this code tells something else...
Test script:
---------------
<?php
class A {
protected $var;
private static $instance = NULL;
public static function getInstance() {
if (is_null(self::$instance))
self::$instance = new A();
return self::$instance;
}
protected function __construct() {
echo "creating instance of A\n";
$this->var = "existing var in instance of A \n";
}
public function show() {
echo $this->var;
}
public function __destruct() {
echo "deleting instance of A\n";
}
}
class B {
private static $instance = NULL;
public static function getInstance() {
if (is_null(self::$instance))
self::$instance = new B();
return self::$instance;
}
protected function __construct() {
echo "creating instance of B\n";
}
public function __destruct() {
A::getInstance()->show();
echo "deleting instance of B\n";
}
}
header('Content-type: text/plain');
A::getInstance()->show();
B::getInstance();
?>
Expected result:
----------------
Some error?
Actual result:
--------------
creating instance of A
existing var in instance of A
creating instance of B
deleting instance of A
existing var in instance of A
deleting instance of B
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Dec 20 21:00:01 2025 UTC |
Actually, executing the destructor doesn't destroy the object, but rather the destructor is called by the PHP engine before the object is destroyed (i.e. its memory is released). However, PHP makes no guarantee that the destructor is called *immediately* before destroying the object. Consider the following script with a cyclic reference between $a and $b: <?php class A { function __destruct() { $this->b->tell(); } function tell() { echo "I'm an instance of A\n"; } } class B { function __destruct() { $this->a->tell(); } function tell() { echo "I'm an instance of B\n"; } } $a = new A(); $b = new B(); $a->b = $b; $b->a = $a; Neither object can't be destroyed as long as the other is alive. To be able to fulfill the contract that all destructors are called, the engine has to call both destructors first, and only then can destroy both objects. Even if there is no cyclic reference, as in the test script of the OP, detecting that during the shutdown sequence is expensive (if possible at all), so the engine calls all destructors (in undefined order[1]), before destroying the objects. So, IMHO, this is not a bug, but rather a WONTFIX. [1] <http://php.net/manual/en/language.oop5.decon.php#language.oop5.decon.destructor>