Unbekannter, generaler PDO Fehler

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Unbekannter, generaler PDO Fehler

    Guten Tag,
    ich habe foglendes Problem:
    Ich bin dabei eine eigene Sitzungsverwaltung zu schreiben und möchte dies über PDO ermöglichen.
    Dazu habe ich einmal eine Verbindung über die Abstraktionsschnittstelle PDO bereitgestellt:

    Quellcode

    1. <?php//Namespace der Klassenamespace inc\classes;
    2. /** * Abstraktionsschicht für die Datenbank * * Verbindet zur Datenbank und kapselt alle Anfragen an die * Datenbank. Nutzbar mit diversen Datenbanken (MySQL, SQLite, Oracle, etc.) * */
    3. class PDO{ //Datenbankverbindungsobjekt public $PDO = null; //aktuelles preparedStatement public $preparedStatement = null;
    4. /** * Verbindet zur Datenbank und gibt ggf. eine * Fehlermeldung zurück. * */ public function __construct($dsn, $user, $password) { try { //Neues PDO-Objekt $this->PDO = new \PDO($dsn,$user,$password); //Fehlermeldungen sollen "geworfen" werden $this->PDO->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { //Fehlerbehandlung (bspw. E-Mail an Admin) die('<div style="color:red;">'.$e->getMessage().'</div>'); } }
    5. /** * Führt eine SQL-Anfrage durch. * * @param text Die SQL-Anfrage * * @return Array Gibt eine Ergebnismenge zurück */ public function query($sql) { try { //PDO-Anfrage durchführen $pdoStmt = $this->PDO->query($sql); //Liegt eine leere Ergebnismenge vor? ($pdoStmt->rowCount()==0)? $return = array(): //Array mit den Daten $stmt = $pdoStmt->fetchAll(); //Statement schließen $pdoStmt->closeCursor(); return $stmt; } catch(PDOException $e) { //Fehlerbehandlung (bspw. E-Mail an Admin) echo '<div style="color:red;">'.$e->getMessage().'</div>'; return false; } } /** * Legt ein "prepared Statement" an * * @param String Statement mit Platzhalter-Parametern */ public function prepareStatement($statement) { //Prepared Statement vorbereiten $this->preparedStatement = $this->PDO->prepare($statement); if($this->preparedStatement===false) { //Fehlerbehandlung (bspw. E-Mail an Admin) echo '<div style="color:red;">Prepared Statement konnte nicht vorbereitet werden.</div>'; } } /** * Führt ein zuvor angelegtes preparedStatement aus * * @param Array Die Parameter für das prepared Statement. * * @return Array Ergebnis der Anfrage */ public function execute($params = array()) { //Wenn noch kein Statement angelegt ist, wird hier abgebrochen. if($this->preparedStatement==null)return false; try { //PDO-Anfrage durchführen $this->preparedStatement->execute($params); //Wenn keine Daten zurück kamen if($this->preparedStatement->columnCount()==0)return array(); //Andernfalls die Daten als Array zurückgeben return $this->preparedStatement->fetchAll(); } catch(PDOException $e) { //Fehlerbehandlung (bspw. E-Mail an Admin) echo '<div style="color:red;">'.$e->getMessage().'</div>'; return false; } }}?>


    Soweit so gut, nun wollte ich einen eigene Sessionhandler erstellen:

    Quellcode

    1. <?php//Namespace der Klassenamespace inc\classes;
    2. /** * SessionHandler * */class SessionHandler {
    3. private $DB = null;
    4. /** * Konstruktor */ public function __construct($DB) { $this->DB = $DB;
    5. // Den SessionHandler auf die Methoden // dieser Klasse setzen session_set_save_handler(array ($this, '_open'), array ($this, '_close'), array ($this, '_read'), array ($this, '_write'), array ($this, '_destroy'), array ($this, '_gc'));
    6. // Session starten session_start(); //session_write_close(); register_shutdown_function('session_write_close'); }
    7. /** * Öffnen der Session * * @return boolean Gibt immer true zurück */ public function _open($path, $name) { return true; }
    8. /** * Session schließen * * @return boolean Gibt immer true zurück */ public function _close() { //Ruft den Garbage-Collector auf. $this->_gc(0); return true; }
    9. /** * Session-Daten aus der Datenbank auslesen * * @return varchar Gibt entweder die Sitzungswerte oder einen leeren String zurück */ public function _read($sesID) { $sessionStatement = "SELECT * FROM " . DB_TABLEPREFIX . "sessions"." WHERE id = '$sesID'"; $result = $this->DB->query($sessionStatement); if ($result === false) { return ''; }
    10. if (count($result) > 0) {
    11. return $result[0]["value"]; } else { return ''; } }
    12. /** * Neue Daten in die Datenbank schreiben * * @param varchar eindeutige Sessionid * @param Array Alle Daten der Session * * @return boolean Gibt den Status des Schreibens zurück */ public function _write($sesID, $data) { //Nur schreiben, wenn Daten übergeben werden if($data == null) { return true; } //Statement um eine bestehende Session "upzudaten" $sessionStatement = "UPDATE " . DB_TABLEPREFIX . "sessions "." SET lastUpdated='".time()."', value='$data' WHERE id='$sesID'"; $update = $this->DB->query($sessionStatement);
    13. //Ergebnis prüfen if ($update === false) { //Fehler in der Datenbank return false; } if ($this->DB->MySQLiObj->affected_rows) { //bestehende Session "upgedated" return true; } //Ansonsten muss eine neue Session erstellt werden $sessionStatement = "INSERT INTO " . DB_TABLEPREFIX . "sessions "." (id, lastUpdated, start, value)"." VALUES ('$sesID', '".time()."', '".time()."', '$data')"; $update = $this->DB->query($sessionStatement);
    14. //Ergebnis zurückgeben return $update; }
    15. /** * Session aus der Datenbank löschen * * @param varchar eindeutige Session-Nr. * * @return boolean Gibt den Status des Zerstörens zurück */ public function _destroy($sesID) { $sessionStatement = "DELETE FROM " . DB_TABLEPREFIX . "sessions "." WHERE id = '$sesID'"; $result = $this->DB->query($sessionStatement); //Ergebnis zurückgeben (true|false) return $result; }
    16. /** * Müll-Sammler ;-) * * Löscht abgelaufene Sessions aus der Datenbank * * @return boolean Gibt den Status des Bereinigens zurück */ public function _gc($life) { //Zeitpunkt, zu dem die Session als abgelaufen gilt. //Hier 15 min $sessionLife = strtotime("-15 minutes");
    17. $sessionStatement = "DELETE FROM " . DB_TABLEPREFIX . "sessions "." WHERE lastUpdated < $sessionLife"; $result = $this->DB->query($sessionStatement); //Ergebnis zurückgeben return $result; }}?>
    Alles anzeigen


    Ohne PreparedStatements und nur über Query taucht bereits dieser Fehler auf:

    Quellcode

    1. Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error' in C:\xampp\htdocs\smartPHP\inc\classes\class.PDO.php:58 Stack trace: #0 C:\xampp\htdocs\smartPHP\inc\classes\class.PDO.php(xx): PDOStatement->fetchAll() #1 C:\xampp\htdocs\smartPHP\inc\classes\class.SessionHandler.php(xx): inc\classes\PDO->query('UPDATE sp_sessi...') #2 [internal function]: inc\classes\SessionHandler->_write('u4vdetqkru9bsv9...', 'username|s:5:"A...') #3 [internal function]: session_write_close() #4 {main} thrown inC:\xampp\htdocs\smartPHP\inc\classes\class.PDO.php on line xx



    Die Zeilenangabe habe ich weggelassen, da aufgrund der Codeformatierung die Zeilen hier nicht mehr stimmen werden.
    Obwohl ich mehrere Versuche, wie $this->PDO->closeCursor(); und andere Möglichkeiten durch bin finde ich keine passende Lösung.


    Dieser Fehler behebt sich ( ohne, das ich es erklären kann), sobald ich es durch preparedStatements ersetzen, jedoch gibt bei mir die $tstmt->execute nie einen Wert zurück, daher ist die Methode in der Session _write dabei und erledigt sowohl den Update-Befehl, als auch den Insert.
    Auch wenn hier noch das alte $this->MySQLiObj->affected_rows steht, so geben auch alle anderen Funktionen array(0){} zurück und keinen Inhalt.

    Ich weiß leider nicht weiter und hoffe auf Hilfe.

    Vielen Dank.
    Rhythmbeat

    PS: Ich kann mich seltsamerweise nicht registrieren, da als Fehler "fehlende Rechte" auftaucht. :)
  • Hallo Szabo,
    danke für deien Antwort, also die Punkte, die du erwähntest sind aufgrund von Copy und Paste-Fehler entstanden und die formatierung ist im Original sauber und strukturiert, nur wurde in diesem Beispiel die Formatierung aufgehoben.
    Und den ertsen Beitrag kann ich leider nicht bearbeiten, da ich nur Besucher bin, wiederum registrieren ist nicht möglich, da ich "keine zugriffsrechte" auf die Seite habe nach dem "Absenden"-Button. Tut mir Leid.

    Ein erneuter Versuch ohne [code] oder Syntax, da sonst eigenständig formartiert wird:
    SessionHandler:

    Quellcode

    1. <?php
    2. //Namespace der Klasse
    3. namespace inc\classes;
    4. /**
    5. * SessionHandler
    6. *
    7. */
    8. class SessionHandler {
    9. private $DB = null;
    10. /**
    11. * Konstruktor
    12. */
    13. public function __construct($DB)
    14. {
    15. $this->DB = $DB;
    16. // Den SessionHandler auf die Methoden
    17. // dieser Klasse setzen
    18. session_set_save_handler(array ($this, '_open'),
    19. array ($this, '_close'),
    20. array ($this, '_read'),
    21. array ($this, '_write'),
    22. array ($this, '_destroy'),
    23. array ($this, '_gc'));
    24. // Session starten
    25. session_start();
    26. //session_write_close();
    27. register_shutdown_function('session_write_close');
    28. }
    29. /**
    30. * Öffnen der Session
    31. *
    32. * @return boolean Gibt immer true zurück
    33. */
    34. public function _open($path, $name) {
    35. return true;
    36. }
    37. /**
    38. * Session schließen
    39. *
    40. * @return boolean Gibt immer true zurück
    41. */
    42. public function _close() {
    43. //Ruft den Garbage-Collector auf.
    44. $this->_gc(0);
    45. return true;
    46. }
    47. /**
    48. * Session-Daten aus der Datenbank auslesen
    49. *
    50. * @return varchar Gibt entweder die Sitzungswerte oder einen leeren String zurück
    51. */
    52. public function _read($sesID) {
    53. $sessionStatement = "SELECT * FROM " . DB_TABLEPREFIX . "sessions WHERE id = '$sesID'";
    54. $result = $this->DB->query($sessionStatement);
    55. if ($result === false) {
    56. return '';
    57. }
    58. if (count($result) > 0) {
    59. return $result[0]["value"];
    60. } else {
    61. return '';
    62. }
    63. }
    64. /**
    65. * Neue Daten in die Datenbank schreiben
    66. *
    67. * @param varchar eindeutige Sessionid
    68. * @param Array Alle Daten der Session
    69. *
    70. * @return boolean Gibt den Status des Schreibens zurück
    71. */
    72. public function _write($sesID, $data) {
    73. //Nur schreiben, wenn Daten übergeben werden
    74. if($data == null)
    75. {
    76. return true;
    77. }
    78. //Statement um eine bestehende Session "upzudaten"
    79. $sessionStatement = "UPDATE " . DB_TABLEPREFIX . "sessions SET lastUpdated='".time()."', value='$data' WHERE id='$sesID'";
    80. $update = $this->DB->query($sessionStatement);
    81. //Ergebnis prüfen
    82. if ($update === false) {
    83. //Fehler in der Datenbank
    84. return false;
    85. }
    86. if ($this->DB->MySQLiObj->affected_rows) {
    87. //bestehende Session "upgedated"
    88. return true;
    89. }
    90. //Ansonsten muss eine neue Session erstellt werden
    91. $sessionStatement = "INSERT INTO " . DB_TABLEPREFIX . "sessions (id, lastUpdated, start, value) VALUES ('$sesID', '".time()."', '".time()."', '$data')";
    92. $update = $this->DB->query($sessionStatement);
    93. //Ergebnis zurückgeben
    94. return $update;
    95. }
    96. /**
    97. * Session aus der Datenbank löschen
    98. *
    99. * @param varchar eindeutige Session-Nr.
    100. *
    101. * @return boolean Gibt den Status des Zerstörens zurück
    102. */
    103. public function _destroy($sesID) {
    104. $sessionStatement = "DELETE FROM " . DB_TABLEPREFIX . "sessions "." WHERE id = '$sesID'";
    105. $result = $this->DB->query($sessionStatement);
    106. //Ergebnis zurückgeben (true|false)
    107. return $result;
    108. }
    109. /**
    110. * Müll-Sammler ;-)
    111. *
    112. * Löscht abgelaufene Sessions aus der Datenbank
    113. *
    114. * @return boolean Gibt den Status des Bereinigens zurück
    115. */
    116. public function _gc($life) {
    117. //Zeitpunkt, zu dem die Session als abgelaufen gilt.
    118. //Hier 15 min
    119. $sessionLife = strtotime("-15 minutes");
    120. $sessionStatement = "DELETE FROM " . DB_TABLEPREFIX . "sessions "." WHERE lastUpdated < $sessionLife";
    121. $result = $this->DB->query($sessionStatement);
    122. //Ergebnis zurückgeben
    123. return $result;
    124. }
    125. }
    126. ?>
    Alles anzeigen



    PDO-Klasse:

    Quellcode

    1. <?php
    2. //Namespace der Klasse
    3. namespace inc\classes;
    4. /**
    5. * Abstraktionsschicht für die Datenbank
    6. *
    7. * Verbindet zur Datenbank und kapselt alle Anfragen an die
    8. * Datenbank. Nutzbar mit diversen Datenbanken (MySQL, SQLite, Oracle, etc.)
    9. *
    10. */
    11. class PDO
    12. {
    13. //Datenbankverbindungsobjekt
    14. public $PDO = null;
    15. //aktuelles preparedStatement
    16. public $preparedStatement = null;
    17. /**
    18. * Verbindet zur Datenbank und gibt ggf. eine
    19. * Fehlermeldung zurück.
    20. *
    21. */
    22. public function __construct($dsn, $user, $password)
    23. {
    24. try
    25. {
    26. //Neues PDO-Objekt
    27. $this->PDO = new \PDO($dsn,$user,$password);
    28. //Fehlermeldungen sollen "geworfen" werden
    29. $this->PDO->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    30. }
    31. catch (PDOException $e)
    32. {
    33. //Fehlerbehandlung (bspw. E-Mail an Admin)
    34. die('<div style="color:red;">'.$e->getMessage().'</div>');
    35. }
    36. }
    37. /**
    38. * Führt eine SQL-Anfrage durch.
    39. *
    40. * @param text Die SQL-Anfrage
    41. *
    42. * @return Array Gibt eine Ergebnismenge zurück
    43. */
    44. public function query($sql)
    45. {
    46. try
    47. {
    48. //PDO-Anfrage durchführen
    49. $pdoStmt = $this->PDO->query($sql);
    50. //Liegt eine leere Ergebnismenge vor?
    51. ($pdoStmt->rowCount()==0)? $return = array():
    52. //Array mit den Daten
    53. $stmt = $pdoStmt->fetchAll();
    54. //Statement schließen
    55. $pdoStmt->closeCursor();
    56. return $stmt;
    57. }
    58. catch(PDOException $e)
    59. {
    60. //Fehlerbehandlung (bspw. E-Mail an Admin)
    61. echo '<div style="color:red;">'.$e->getMessage().'</div>';
    62. return false;
    63. }
    64. }
    65. /**
    66. * Legt ein "prepared Statement" an
    67. *
    68. * @param String Statement mit Platzhalter-Parametern
    69. */
    70. public function prepareStatement($statement)
    71. {
    72. //Prepared Statement vorbereiten
    73. $this->preparedStatement = $this->PDO->prepare($statement);
    74. if($this->preparedStatement===false)
    75. {
    76. //Fehlerbehandlung (bspw. E-Mail an Admin)
    77. echo '<div style="color:red;">Prepared Statement konnte nicht vorbereitet werden.</div>';
    78. }
    79. }
    80. /**
    81. * Führt ein zuvor angelegtes preparedStatement aus
    82. *
    83. * @param Array Die Parameter für das prepared Statement.
    84. *
    85. * @return Array Ergebnis der Anfrage
    86. */
    87. public function execute($params = array())
    88. {
    89. //Wenn noch kein Statement angelegt ist, wird hier abgebrochen.
    90. if($this->preparedStatement==null)return false;
    91. try
    92. {
    93. //PDO-Anfrage durchführen
    94. $this->preparedStatement->execute($params);
    95. //Wenn keine Daten zurück kamen
    96. if($this->preparedStatement->columnCount()==0)return array();
    97. //Andernfalls die Daten als Array zurückgeben
    98. return $this->preparedStatement->fetchAll();
    99. }
    100. catch(PDOException $e)
    101. {
    102. //Fehlerbehandlung (bspw. E-Mail an Admin)
    103. echo '<div style="color:red;">'.$e->getMessage().'</div>';
    104. return false;
    105. }
    106. }
    107. }
    108. ?>
    Alles anzeigen