2008-10-27 11 views
11

Die Frage ist, ob eine Datenbankverbindung durch Referenz oder Wert übergeben werden soll?Datenbankverbindung durch Referenz in PHP übergeben

Für mich frage ich speziell eine PHP zu MySQL-Verbindung, aber ich denke, dass es für alle Datenbanken gilt.

Ich habe gehört, dass in PHP, wenn Sie eine Variable an eine Funktion oder ein Objekt übergeben, dass es im Speicher kopiert wird und daher sofort doppelt so viel Speicher verwendet. Ich habe auch gehört, dass es nur kopiert wird, wenn Änderungen an dem Wert vorgenommen wurden (z. B. wenn ein Schlüssel einem Array hinzugefügt oder daraus entfernt wird).

In einer Datenbankverbindung würde ich denken, dass es in der Funktion geändert wird, da die Abfrage Dinge wie die letzte INSERT ID oder NUM Zeilen ändern könnte. (Ich denke, das ist eine andere Frage: Sind Dinge wie num Zeilen und einfügen ID in der Verbindung gespeichert oder ein tatsächlicher Anruf zurück zur Datenbank gemacht wird?)

Also, spielt es eine Rolle Speicher oder Geschwindigkeit weise, wenn die Verbindung besteht durch Referenz oder Wert? Macht es einen Unterschied zwischen PHP 4 und 5?

Antwort

16

Eine PHP-Ressource ist ein spezieller Typ, der bereits eine Referenz ist. Es nach Wert oder explizit durch Verweis übergeben wird keinen Unterschied machen (dh es ist immer noch eine Referenz). Sie können dies unter PHP4 selbst überprüfen:

function get_connection() { 
    $test = mysql_connect('localhost', 'user', 'password'); 
    mysql_select_db('db'); 
    return $test; 
} 

$conn1 = get_connection(); 
$conn2 = get_connection(); // "copied" resource under PHP4 

$query = "INSERT INTO test_table (id, field) VALUES ('', 'test')"; 
mysql_query($query, $conn1); 
print mysql_insert_id($conn1)."<br />"; // prints 1 

mysql_query($query, $conn2); 
print mysql_insert_id($conn2)."<br />"; // prints 2 

print mysql_insert_id($conn1); // prints 2, would print 1 if this was not a reference 
4

Call-Time-Pass-by-Referenz wird abgeschrieben, also würde ich nicht die zuerst beschriebene Methode verwenden. Im Allgemeinen werden Ressourcen standardmäßig per Referenz in PHP 5 übergeben. Es sollte also keine Referenzen geben, und Sie sollten nie mehr als eine Datenbankverbindung öffnen, wenn Sie sie nicht wirklich brauchen.

Persönlich verwende ich eine Singleton-Factory-Klasse für meine Datenbankverbindungen, und wenn ich eine Datenbankreferenz brauche, rufe ich einfach Factory :: database() an, auf diese Weise muss ich mich nicht um mehrere Verbindungen kümmern Referenzen erhalten

<?php 
Class Factory 
{ 
    private static $local_db; 

/** 
* Open new local database connection 
* 
* @return MySql 
*/ 
public static function localDatabase() { 
    if (!is_a(self::$local_db, "MySql")) { 
     self::$local_db = new MySql(false); 
     self::$local_db->connect(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     self::$local_db->debugging = DEBUG; 
    } 
    return self::$local_db; 
} 
} 
?> 
+2

"Funktion DoSomething1 (& $ connection) {...}" ist keine Call-Time-Pass-by-Referenz –

+1

Ich wollte nur das gleiche sagen wie Tom - das ist KEIN Anruf-Time Pass-by- Referenz, die, wie der Name schon sagt, zur Zeit der Funktion auftritt. Berufung, keine Erklärung. Call-Time-Pass-by-Referenz sieht so aus

+1

Der globale Status ist normalerweise eine schlechte Antwort auf jedes Problem. – troelskn

0

Ich habe nicht wirklich eine konkrete Antwort für PHP, aber im Allgemeinen wäre es mir scheinen, dass Sie dies anhand passieren würde, wenn Sie wollen nicht explizit sicher sind, dass Sie die Performance-Probleme auftreten, wenn vorbei Wert.

1

Eine Datenbank Verbindung eigentlich nicht die zugrunde liegenden Werte halten, so dass Sie sich keine Sorgen über Zuordnungen innerhalb einer Funktion zu verlieren. Metaphorisch kann man sich eine DB Verbindung als sagen, eine Startbahn Nummer - "OK, DB Connection 12 ist für eine Abfrage verwendet werden" - die Abfrage und Ergebnissatz verwenden die Verbindung, und kann benötigen für eine Weile exklusiven Zugriff, aber die Verbindung weiß nichts über die zugrunde liegenden Daten.

0

Im Allgemeinen sind Referenzen in PHP nicht schneller. Es ist ein weit verbreitetes Missverständnis, da sie C-Zeigern semantisch ähnlich sind, so dass Leute, die mit C vertraut sind, oft davon ausgehen, dass sie auf die gleiche Weise funktionieren. Nicht so. Tatsächlich sind Verweise ein kleines bisschen langsamer als Kopien, es sei denn, Sie ordnen der Variablen tatsächlich zu (was in jedem Fall ein schlechter Stil ist, es sei denn, die Variable ist ein Objekt).

PHP hat einen Mechanismus copy-on-write genannt, was bedeutet, dass eine Variable kopiert nicht tatsächlich ist, bevor es ihn braucht. Sie können eine große Datenstruktur an eine Funktion übergeben. Solange es nur davon liest, macht es keinen Unterschied.Ein Verweis benötigt jedoch einen zusätzlichen Eintrag in den internen Registern, so dass es tatsächlich einige zusätzliche Verarbeitung benötigen würde (obwohl kaum bemerkbar).

1

Ein paar Leute haben gesagt, dass Sie sich nicht um PHP 5 kümmern müssen. Das ist falsch, wenn Sie ein Datenbankobjekt haben, das Sie für alle Zugriffe verwenden. In diesem Fall müssen Sie als Referenz übergeben werden, andernfalls wird ein neues DB-Objekt instanziiert, das (oft) eine neue Verbindung zur Datenbank erstellt.

Ich entdeckte dieses mit XDebug & WinCacheGrind, die alle Destruktoren freundlich zeigt, die aufgerufen - in meinem Fall eine halfdozen oder mehrere Datenbankobjekte.

Um zu verdeutlichen: Der Grund, warum ich darauf hinweise, ist, dass dies eine übliche Art der Verwendung von Datenbankverbindungen ist, anstelle der rohen Verbindungsressource.

5

Es ist nicht die Geschwindigkeit, mit der Sie sich befassen sollten, sondern die Erinnerung.

In PHP 4 sollten Dinge wie Datenbankverbindungen und Resultsets explizit per Referenz übergeben werden. In PHP 5 geschieht dies automatisch, Sie müssen es also nicht explizit machen.

BTW, Singleton Methoden zum Erstellen von Datenbank-Handles sind eine gute Idee: Sie können $db = & Database::Connection(); tun und immer das richtige Handle bekommen. Dies erspart Ihnen die Verwendung einer globalen und die statische Methode kann zusätzliche Magie (wie das automatische Öffnen) für Sie tun. Seien Sie vorsichtig, wenn Ihre Anwendung genug skaliert, dass sie mehrere Datenbanken benötigt: dann muss Ihre Zauberfunktion wissen, wie Sie die richtige zurückgeben können. IME das ist nicht sehr schwierig; Der grundlegende Weg, dies zu lösen, ist für die Codeschicht, die den DB-Griff benötigt, um zu wissen, wie man nach dem richtigen fragt.

Verwandte Themen