dedlfix: Datenbankverbindung aus Session

Beitrag lesen

echo $begrüßung;

Du solltest nicht zu sehr auf den Hamster/Hamstar hören. Er hat zwar grundlegende Datenbankahnung kennt sich jedoch mit den Details zu MySQL und PHP nicht weiter aus. Das hält ihn aber nicht vom Antworten ab, was dann teilweise zu derben Fehlaussagen führt.

Zunächst etwas Kleinkram:

catch(Exception $e)
   {
    echo $e->getMessage();
    $this->mysqli = FALSE;
    exit();
   }

Wenn du sowieso abbrichst (exit()), brauchst du $this->mysqli nicht mehr durch das Zuweisen von false zum Destrukten zu bewegen, das passiert durch das Scriptende sowieso. Außerdem gehört es sich nicht für die Datenbankklasse, das Script zu beenden. Auftretende Fehler sollte sie an die aufrufende Instanz weitergeben, damit diese angemessen reagieren kann, z.B. eine (weniger detaillierte, denn diese Information interessiert den Anwender nicht) Fehlermeldung im Layout der restlichen Anwendung ausgeben.

include('temp.php');

include ist ein Sprachkonstrukt, keine Funktion. Es benötigt keine Klammern um den Dateinamen. Die Klammern bewirken hier nur, dass der darin enthaltene Ausdruck, der nur aus dem String besteht, berechnet wird, und dann erst dem include übergeben wird.

Nun zum eigentlichen Problem:

Was mache ich falsch?

Der Fehler sollte deutlicher sichtbar werden, wenn du var_dump() statt print_r() zur Kontrollausgabe verwendetest. Statt "db_handler Object" wird dann "object(db_handler)#1" angezeigt. Die #1 gibt dabei an, um welche Instanz es sich handelt. Probier das erstmal aus, bevor du weiterliest ...

function __wakeup()
  {
   echo "<br><b>__wakeup</b><br>";
   print_r($this);
   self::$uniqueInstance = new db_handler;
  }

In __wakeup() lässt du dir mit $this das eben aus der Session wiederhergestellte Objekt #1 anzeigen. Danach erzeugst du ein neues Objekt #2 (inklusive __construct() und connect()) und weist es self::$uniqueInstance zu. Die aufgeweckte #1 hat __construct() und damit auch connect() nicht durchlaufen. Mit $_SESSION['db'] greifst du auf das wiederhergestellte Objekt #1 zu, nicht auf das konnektierte #2 in self::$uniqueInstance.

Allgemein wäre es besser, wenn du den Connect erst dann ausführst, wenn er wirklich benötigt wird, nicht schon prophylaktisch beim Konstruieren des Objekts. Jede Methode, die eine Datenbankverbindung braucht, muss dazu connect() aufrufen, welches die Verbindungskennung (bzw. das mysqli-Objekt) zurückliefert. Werden nur Methoden aufgerufen die keine Verbindung brauchen, gibt es kein unnötiges Connect.

Das Singleton-Pattern brauchst du dann nur für die über connect() abrufbare Verbindungskennung (bzw. das mysqli-Objekt), die in einer Klassenvariable (self::$connection) abgelegt wird. DB-Handler-Objekte kann es durchaus mehrere geben, z.B. für jedes Statement eine Instanz. Die Result-Kennung wäre dann eine Objekt- bzw. Instanzvariable. Damit kannst du eine Abfrage starten, und noch bevor das Ergebnis komplett ausgelesen ist, kannst du eine weitere Abfrage starten, deren Result-Kennung in ihrer eigenen Instanz gehalten wird. (Klappt nur nicht bei ungepufferten Abfragen. Also entweder mysqli::query() ohne zweiten Parameter bzw. mit MYSQLI_STORE_RESULT oder mysqli::real_query() mit mysqli::store_result() verwenden.)

Das Datenbankzugriffsobjekt solltest du nicht in der Session ablegen. Die Verbindung bleibt, wie du weißt, nicht erhalten, sie wird zum Scriptende geschlossen. Beim erneuten Start der Session konnektierst du sowieso erneut. Auch die Result-Kennung nützt dir nichts, da nur zusammen mit der Verbindung Daten von der DB gelesen werden können. Wenn du etwas in der Session ablegen möchtest, sollten das fertig abgefragte Daten (eigenes Objekt, Array oder sonstige Struktur) sein, von denen du ausgehen kannst, dass sie sich während der Session-Laufzeit nicht in der Datenbank ändern. Ansonsten solltest du andere Cache-Mechanismen verwenden, die auch sessionübergreifend bzw. -unabhängig funktionieren, und damit Daten als unbrauchbar, weil geändert, kennzeichnen können.

echo "$verabschiedung $name";