[PHP5] Objekt aus einem anderen Objekt heraus zerstören

en2k

Erfahrenes Mitglied
Hallo,

ich habe folgendes Problem: Ich möchte ein Objekt aus einem anderen Objekt heraus zerstören. Beide Objekte müssen allerdings global existieren, deshalb die Einbindung von $myA über 'global'. Aber anscheinend funktioniert das so nicht.

PHP:
<?php
	class a {
		public function __construct() {
			echo "Konstruktor A<br>";
		}
		
		public function __destruct() {
			echo "Destruktor A<br>";
		}
		
	}
	
	class b {
		public function __construct() {
			global $myA;
			$myA = new a();
			echo "Konstruktor B<br>";
		}
		
		public function __destruct() {
			global $myA;
			unset($myA);
			echo "Destruktor B<br>";
		}
		
	}
	
	
	$myB = new b();
	unset($myB);
	echo "Ende<br>";
?>

Das Skript gibt mir folgende Ausgabe zurück:
PHP:
Konstruktor A
Konstruktor B
Destruktor B
Ende
Destruktor A

Wie man sieht, wird der Destruktor von $myA erst am Skriptende aufgerufen. Aber wieso? Kann man Variablen, die man per global einbindet, nicht mittels unset löschen? Anlegen geht ja schließlich auch...

Vielen Dank im Voraus.

Nino
 
Hi,
das Prolblem hat mich gerade erstmal etwas stutzig gemacht, denke aber ich habe die Lösung gefunden.

Laut Manual wird ein Destruktor erst aufgerufen, wenn alle Referenzen auf das Objekt gelöscht werden.
Natürlich könnte man meinen, das nach dem "unset()" dies so ist, aber ich habe eine bischen getestet:

PHP:
class b {
// sonst der gleiche code...
    public function __destruct() {
        global $myA;
        var_dump($GLOBALS);  // 'myA' existiert, 'myB' schon entfernt
        unset($myA);
        var_dump($myA);          // gibt NULL zurück, objekt aus userscope gelöscht
        var_dump($GLOBALS);  // 'myA' existiert noch!!
        unset($GLOBALS['myA']);
        var_dump($GLOBALS);    // 'myA' nun auch verschwunden
        echo "Destruktor B\n";
    }

}
Wie man sieht, wird wohl noch eine Referenz im $GLOBALS array gehalten, welche erst mit Scriptende gecleared wird.
Wenn man explizit die Referenz von myA in $GLOBALS löscht, dann wird der Destruktor auch wie gewünscht aufgerufen.
Habe mal den Bugtracker befragt und einen ähnlichen Eintrag gefunden:
http://bugs.php.net/bug.php?id=39728
hier wird beschrieben, das man via unset() nur die Variable/Object aus dem Userscope entfernt, aber die Referenz weiter im GLOBALS array gehalten wird und der vorgeschlagende Weg ist, die Referenz ebenfalls aus dem GLOBALS zu entfernen.
Würde daher sagen, das das Verhalten "works as designed" ist.

Da dies nur ein Testcode ist weiss ich nicht, was du eigentlich vor hast, aber persönlich versuche ich immer alles aus GLOBALS rauszuhalten und nicht aktiv damit zu arbeiten.
Gerade wenn man mit Objekten arbeitet und damit ja versucht Code/Objekte gezielt vom Rest zu kapseln, macht es keinen Sinn diese Objekte dann wieder in den globalen Scope zu schieben.
Du könntest dein Objekt myA abhängig vom myB machen, indem du eine Referenz von myA als Klassenvariable von myB machst und wenn du Zugriff auf myA brauchst, gehst du über das myB Objekt...
PHP:
<?php
class a {
    var $testvar= = 0;
    public function __construct() {
        echo "Konstruktor A\n";
    }

    public function __destruct() {
        echo "Destruktor A\n";
    }

}

class b {
    protected $myA = NULL;
    public function __construct() {
        $this->myA = new a();
        echo "Konstruktor B\n";
    }

    public function __destruct() {
        echo "Destruktor B\n";
    }
    public function getMyA() {
        RETURN $this->myA;
    }

}


$myB = new b();
$myB->getMyA()->testvar = 1;
unset($myB);
echo "Ende\n";
?>
Grüsse
 
Zurück