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:
Soweit so gut, nun wollte ich einen eigene Sessionhandler erstellen:
Alles anzeigen
Ohne PreparedStatements und nur über Query taucht bereits dieser Fehler auf:
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.
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
- <?php//Namespace der Klassenamespace inc\classes;
- /** * Abstraktionsschicht für die Datenbank * * Verbindet zur Datenbank und kapselt alle Anfragen an die * Datenbank. Nutzbar mit diversen Datenbanken (MySQL, SQLite, Oracle, etc.) * */
- class PDO{ //Datenbankverbindungsobjekt public $PDO = null; //aktuelles preparedStatement public $preparedStatement = null;
- /** * 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>'); } }
- /** * 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
- <?php//Namespace der Klassenamespace inc\classes;
- /** * SessionHandler * */class SessionHandler {
- private $DB = null;
- /** * Konstruktor */ public function __construct($DB) { $this->DB = $DB;
- // 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'));
- // Session starten session_start(); //session_write_close(); register_shutdown_function('session_write_close'); }
- /** * Öffnen der Session * * @return boolean Gibt immer true zurück */ public function _open($path, $name) { return true; }
- /** * Session schließen * * @return boolean Gibt immer true zurück */ public function _close() { //Ruft den Garbage-Collector auf. $this->_gc(0); return true; }
- /** * 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 ''; }
- if (count($result) > 0) {
- return $result[0]["value"]; } else { return ''; } }
- /** * 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);
- //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);
- //Ergebnis zurückgeben return $update; }
- /** * 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; }
- /** * 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");
- $sessionStatement = "DELETE FROM " . DB_TABLEPREFIX . "sessions "." WHERE lastUpdated < $sessionLife"; $result = $this->DB->query($sessionStatement); //Ergebnis zurückgeben return $result; }}?>
Ohne PreparedStatements und nur über Query taucht bereits dieser Fehler auf:
Quellcode
- 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.