Datenbankverbindung im Konstruktor und Destruktor

9232
percent20

Ich spiele mit verschiedenen Möglichkeiten, um Datenbank-Interaktionen in PHP auszuführen, und eine der Ideen, mit denen ich gespielt habe, ist das Herstellen einer Verbindung mit der DB im Konstruktor und das Trennen der Verbindung im Destruktor. Dies ist der Code aus meiner DatabaseKlasse.

function __construct()
{
  $this->link = mysql_connect($this->server.':'.$this->port, $this->username);
  if(!$this->link)
    die('Could not connect: '.mysql_error());

  if(!mysql_select_db($this->database, $this->link))
    die('Could not select database: '.mysql_error());
}    

function __destruct()
{
  if(mysql_close($this->link))
    $this->link = null; 
}

Dies funktioniert gut, meine einzige Reservierung ist, dass, wenn ich mehrere Verbindungen herstellen muss, um die Datenbank mehrmals aufzurufen, mehrere Verbindungen hergestellt und die Verbindung getrennt wird. Wenn ich das oft mache, sehe ich vielleicht mögliche Probleme. Ist das ein Problem oder gibt es einen besseren Weg, dies zu tun? Und ist mein Code überhaupt überhaupt Schnupftabak?

Antworten
38

5 Antworten auf die Frage

19
rightfold

Sie können MySQLi (PHP-Erweiterung) verwenden, das standardmäßig klassenbasiert ist und nicht MySQL. Es ist sehr einfach mehrere Verbindungen aufzubauen. Sie müssen jedoch immer wissen, welche Verbindung Sie abfragen.


Herzlichen Glückwunsch mit der ersten Frage.

18
LRE

Aus Ihrer Frage schlussfolgere ich, dass Sie über mehrere Instanzen der DB-Klasse nachdenken. In diesem Fall würde ich vorschlagen, die Verbindung auf eine andere Klasse zu abstrahieren und in jeder DB-Instanz einen Verweis auf dieselbe Verbindung zu halten.

Sie könnten dann Ihre Verbindung als Singleton einrichten und somit nur einmal verbinden und trennen.

Entschuldigung im Voraus, wenn ich hier etwas verpasst habe - mein PHP ist alles andere als fließend.

Ja. Ich werde mehrere Instanzen der Datenbankklasse haben. Ich war mir einfach nicht sicher, ob es eine gute Herangehensweise war, um die Verbindung zu abstrahieren, oder ob ich überhaupt sollte. percent20 vor 10 Jahren 0
Die Sache ist die, dass ich in der Vergangenheit mit mehr als einer Verbindung gestochen worden bin, als ich die Verbindung hätte teilen können, also würde ich sagen: "Abstrakt", es sei denn, man kann sich einen sehr guten Grund vorstellen, " LRE vor 10 Jahren 0
16
Wade Tandy

Sie können auch den integrierten PHP-Befehl mysql_pconnect () betrachten. Dies unterscheidet sich von mysql_connect dadurch, dass beim erstmaligen Aufruf eine dauerhafte Verbindung zur Datenbank hergestellt wird. Bei jedem folgenden Mal wird geprüft, ob eine Verbindung zu dieser Datenbank besteht, und diese Verbindung wird stattdessen verwendet. Sie sollten dann den Befehl mysql_close aus dem Destruktor entfernen, da sie zwischen den Seitenladungen bestehen bleiben.

Die PHP-Handbuchseite: http://php.net/manual/de/function.mysql-pconnect.php

Ich habe darüber gelesen und es klingt sehr verlockend. Aber wie schließt man die Verbindung? In den Dokumenten heißt es, dass mysql_close () nicht funktioniert. Verlassen Sie sich einfach auf den mysql-Server, um ihn zu schließen, wenn er so lange inaktiv war. Ich würde gerne wissen, dass nach Beendigung der Arbeit die Verbindung geschlossen wird. percent20 vor 10 Jahren 0
Sie schließen die Verbindung nicht explizit. Es wird schließlich durch die PHP-Interna geschlossen, nachdem eine bestimmte Zeit ohne Verwendung verstrichen ist. Dadurch entfällt der Aufwand für das wiederholte Öffnen und Schließen von Verbindungen, und einzelne Seitenanfragen können wesentlich schneller ausgeführt werden. Wade Tandy vor 10 Jahren 0
Okay, ich werde auch ein bisschen damit spielen. Vielen Dank. percent20 vor 10 Jahren 0
13
cbrulak

Verwenden Sie eine Abstraktionsbibliothek wie Pear MDB2 für Ihre Datenbankverbindung.

Dies abstrahiert die gesamte Verbindungslogik von Ihrem Code. Wenn Sie also Ihre Datenbank (mysql in SQLite usw.) ändern, müssen Sie Ihren Code nicht ändern.

http://pear.php.net/manual/de/package.database.mdb2.php

Die letzte stabile Veröffentlichung war in [2007] (http://pear.php.net/package/MDB2) ... Also entweder ist es gut, dass es nicht aktualisiert werden muss (bezweifle es, da es eine Beta gibt die Werke) oder es ist einfach inaktiv (wahrscheinlicher) Es gibt Tonnen von besseren Abstraktionsschichten (IMHO), die aktiver als diese entwickelt werden. ircmaxell vor 10 Jahren 3
Ich habe PHP seit einiger Zeit nicht mehr verwendet. Fühlen Sie sich also frei, es in diesem Thread hinzuzufügen oder eine neue Antwort zu erstellen. :) Mein Standpunkt ist, dass es eine viel bessere Lösung ist, die Verbindungs- / Abfrage-Logik über eine Bibliothek zu abstrahieren als eine bestimmte Bibliothek. cbrulak vor 10 Jahren 1
10
RobertPitt

Ich glaube nicht, dass es einen Unterschied macht, ob Sie sich innerhalb der Konstruktion oder innerhalb einer Verbindungsmethode mit der Datenbank verbinden. Ich glaube, Sie müssen diese Befehle ändern.

Die Verwendung des Würfels bewirkt, dass das Skript angehalten wird und 1 kleine Nachricht an den Benutzer gesendet wird. Der Benutzer würde denken, dies sei Müll, und nie wieder Ihre Website besuchen :( :(

Was Sie tun sollten, ist das Auffinden von Fehlern und das Umleiten auf eine statische Seite, auf der Sie dem Benutzer eine sehr nette Nachricht anzeigen können, die sich für die technischen Probleme entschuldigt, die Sie haben.

Sie können auch eine Box mit der Aufschrift "Geben Sie Ihre E-Mail-Adresse ein. Wir werden Sie per E-Mail benachrichtigen, wenn Sie wieder online waren. Sie erhalten die Idee."

Was den Code angeht, würde ich folgende Zeilen durchgehen:

class Database
{
    public function __construct($autoconnect = false)
    {
        //Here you would 'globalize' your config and set it locally as a reference.
        if($autoconnect === true)
        {
             $this->connect();
        }
    }

    public function connect()
    {
        if($this->connected() === false)
        {
             $result = $this->driver->sendCommand("connect");
             if($result === true)
             {
                  $this->setConnectionState("active");
                  $this->setConnectionResource($this->driver->sendCommand("get_resource"));
             }else
             {
                 throw new DatabaseConnectionError($this->driver->sendCommand("getDriverError"));
             }
        }
    }
}

Dadurch erhalten Sie auf lange Sicht mehr Funktionen, da jede Aktion innerhalb Ihrer APP entschieden werden kann. Standardmäßig wird nichts automatisch ausgelöst.

Sie können einfach versuchen, Blöcke zu blockieren, um Ihre Fehlerberichte zu verwalten.

+1 für die Verwendung von try / catch. Ich habe auch Probleme mit Fehlern erlebt, die im Konstruktor ausgelöst wurden: Sie haben keine Instanz des Objekts, um den Fallback-Mechanismus zu implementieren, der einen Sinn ergibt, der in meinem Fall große Teile des in der Klasse vorhandenen Codes verwendete ... Ohne gültige Beispiel: Sie können keine Instanzmethoden aufrufen, und ich musste einige statische Methoden erstellen, was nicht ideal war. Eric Bréchemier vor 10 Jahren 0
Danke, aber ich habe Schwierigkeiten, dich zu verstehen. Kannst du bitte deinen Kommentar umformulieren? RobertPitt vor 9 Jahren 0
Sicher :) Ausnahmen zu werfen ist in Ordnung, solange Sie Code hinzufügen, um sie zu fangen. Vermeiden Sie jedoch Code, der Ausnahmen in einem Konstruktor auslöst. Dies kann zu einigen Problemen führen, die ich erlebt habe: Im Fehlerfall haben Sie kein Objekt erstellt, und Sie könnten das in Ihrem catch-Block nicht finden, wenn Sie die für definierte Verhaltensweisen wiederverwenden möchten dieses Objekt. Ich würde eher empfehlen, die Verbindung in einer regulären Methode zu erstellen, z. B. init () oder connect (), die für das Objekt aufgerufen wird, nachdem es erstellt wurde, und nicht direkt im Konstruktor. Eric Bréchemier vor 9 Jahren 0