dedlfix: Wie strukturiertes landen von Klassen in Index.php?

Beitrag lesen

Tach!

Ich finde folgenden Link eigentlich immer sehr gut um die Funktionsweise von modernen Frameworks zu erklären: von flat PHP zu Symfony.

Sehr schöne Erklärung, aber sie haben da einen Fehler drin. Der ist was für aufmerksame Experten und ändert nichts daran, dass man im Prinzip wie dort beschrieben vorgehen kann/sollte.

So steht es im ersten Beispiel:

$link = new PDO("mysql:host=localhost;dbname=blog_db", 'myuser', 'mypassword');
// ...
$link = null;

Nach der Benutzung der PDO-Instanz wird die in der Variable $link gehaltene Referenz durch null ersetzt. Der Garbage Collector kann nun die Instanz wegräumen, da nichts mehr auf sie referenziert.

Dann haben sie es umgebaut. Erstmal zwei Funktionen erstellt,

function open_database_connection() {
    $link = new PDO("mysql:host=localhost;dbname=blog_db", 'myuser', 'mypassword');
    return $link;
}

function close_database_connection($link) {
    $link = null;
}

die dann so verwendet werden:

$link = open_database_connection();
// ...
close_database_connection($link);

Damit wird die Connection nicht mehr freigegeben, weil die Referenz bestehenbleibt. Die Funktion close_database_connection() definiert sich einen Parameter namens $link. Der ist nicht zu verwechseln mit der Variable $link, in der das Ergebnis von open_database_connection() abgelegt wird (im Folgenden als das äußere $link bezeichnet). Und auch das $link innerhalb der letztgenannten Funktion hat nichts mit den beiden anderen $link zu tun. Alle drei sind separate Variablen.

In open_database_connection() wird eine Instanz von PDO erzeugt, und in $link erstellt PHP eine Referenz auf diese Instanz. $link wird zurückgegeben. Damit wird eine weitere Referenz erstellt, wenn diese Rückgabe im äußeren $link ablegt wird. Das $link innerhalb open_database_connection() wird beim Verlassen der Funktion aufgeräumt, somit wird diese Referenz vernichtet und nur noch die im äußeren $link bleibt bestehen. Beim Aufruf von close_database_connection() wird nun für die dortige lokale Variable $link eine weitere Referenz erstellt. Und nur diese wird beim Zuweisen von null überschrieben. Die Referenz im äußeren $link bleibt bestehen. Und somit wird auch die Datenbankverbindung nicht zum Schließen freigegeben. Das passiert erst zum Scriptende, wenn auch das äußere $link von PHP aufgeräumt wird.

Zum Nachvollziehen gibts hier dieses einfache Beispiel

function bar($foo) {
    debug_zval_dump($foo); // 2
    $foo = null;
}

$foo = new stdclass();
debug_zval_dump($foo); // 1

bar($foo);

debug_zval_dump($foo); // 3

$foo = null;
debug_zval_dump($foo); // 4

Die Ausgabe ist

object(stdClass)#1 (0) refcount(2){}
object(stdClass)#1 (0) refcount(4){}
object(stdClass)#1 (0) refcount(2){}
NULL refcount(2)

Die dritte Zeile zeigt, dass $foo immer noch eine Referenz auf das Objekt enthält. Erst in der vierten ist sie weg.

dedlfix.