PHP/Die eigene Sitzungsverwaltung
PHP 5 bietet die Möglichkeit, eigene Funktionen zur Behandlung der Datenein- und -auslagerung zu definieren, die beim Aufruf von "session_register" und "session_unregister" bzw. bei Veränderungen des Arrays "$_SESSION" aufgerufen werden. Diese können eingesetzt werden, um Daten in einer Datenbank zu speichern, die möglicherweise flexibler mit den Informationen umgeht als ein Dateisystem.
Beim Einsatz eigener Sitzungsfunktionen werden nicht die Aufrufe zu "session_register" usw. ersetzt, sondern die dahinterliegenden Funktionen. An den bereits mit Sitzungen arbeitenden Skripts muss nichts geändert werden. Die Definition erfolgt mit zwei Funktionen.
Funktion | Beschreibung |
---|---|
session_module_name("user") | Abschalten des internen Handlers. |
session_set_save_handler | Definition, welche Funktionen nun für die Ausführung zuständig sind. Insgesamt können sechs Funktionen definiert werden: Öffnen, Schliessen, Zurückholen von registrierten Variablen, Registrieren von Variablen, Zerstören der Sitzung und eine Funktion, die von der Garbage Collection aufgerufen wird. Nicht definierte Funktionen werden durch eine leere Zeichenkette ersetzt (""). |
Das kann beispielsweise so aussehen.
session_module_name("user");
session_set_save_handler("ms_open", "ms_close", "ms_read", "ms_write", "ms_destroy", "ms_gc");
|
Die folgende Lösung basiert auf Datenbankzugriffen. Das Skript ist so ausgelegt, dass die nötige Tabelle beim ersten Zugriff automatisch angelegt wird, sodass man es auch ohne Datenbankkentnisse laufen lassen kann. Voraussetzung ist lediglich, dass die Übungsdatenbank "php5test" im lokalen Mysql-Server vorhanden ist. Die verwendete Tabelle "currentsession" hat folgende Struktur. Sie erlaubt zusätzlich die Zuordnung einer Benutzer-ID, die registrierte Benutzer einer Sitzung zuordnet. So gehen Daten nicht verloren, die bereits anonym erfasst wurden, wenn der Benutzer sich später anmeldet.
CREATE TABLE currentsession (
sessionID varchar(32) NOT NULL,
usrID bigint(20) NOT NULL,
variables text NOT NULL,
laccess int(14),
PRIMARY KEY (sessionID),
KEY usrID (usrID)
);
|
Das folgende Skript "session_dbsess.php" beinhaltet nur die Sitzungsklasse "SessionManager". Die Konstanten zu Beginn dienen der Konfiguration und sind je nach verwendeter Datenbank anzupassen. Um zu sehen, wann welche Funktion aufgerufen wird, eignen sich passende "echo"-Befehle in den einzelnen Funktionen.
<?php
## Name session_dbsess.php
class SessionManager
{
const SESSIONNAME = "SESSION";
const SESSIONDB = "php5test";
const DBUSER = "root";
## Passwort ist auch in Funktion SetMySQL" einzutragen
const DBPASS = "";
const DBSERV = "localhost";
const DBDROP = "DROP TABLE currentsession IF EXISTS";
const DBDEFINITION = "CREATE TABLE currentsession (
sessionID varchar(32) NOT NULL,
usrID bigint(20) NOT NULL,
variables text NOT NULL,
laccess int(14),
PRIMARY KEY (sessionID),
KEY usrID (usrID)
);";
private static $DB;
## Der Konstruktor baut die nötigen Bedingungen für eine benutzerdefinierte
## Sitzungsverwaltung auf.
public function __construct()
{
#echo "KONSTRUKTOR<br />\n";
## Vorbereitung der MySQL-Datenbank mit der Methode "SetMySQL"
$this->SetMySQL();
## Setzen der Parameter für die Sitzung
ini_set("session.use_trans_sid", 1);
ini_set("session.use_cookies", 0);
ini_set("session.gc_probability", 1);
session_module_name("user");
## Rückruffunktionen, hier als Methoden der Klasse "SessionManager"
session_set_save_handler(array("SessionManager", "ms_open"),
array("SessionManager", "ms_close"),
array("SessionManager", "ms_read"),
array("SessionManager", "ms_write"),
array("SessionManager", "ms_destroy"),
array("SessionManager", "ms_gc")
);
session_name(self::SESSIONNAME);
session_start();
}
## Prüfung, ob Tabelle "currentsession" vorhanden ist
private function SetTable()
{
$tbl = mysql_list_tables(self::SESSIONDB, self::$DB);
while ($t = mysql_fetch_assoc($tbl))
{
if ($t['Tables_in_'.self::SESSIONDB] == "currentsession")
{
return;
}
}
mysql_query(self::DBDROP, self::$DB);
mysql_query(self::DBDEFINITION, self::$DB);
}
## Prüfung, ob Datenbank "php5test" vorhanden ist
private function SetMySQL()
{
self::$DB = @mysql_connect("localhost", "root", "");
if (self::$DB !== FALSE)
{
$dbs = mysql_list_dbs(self::$DB);
while ($db = mysql_fetch_assoc($dbs))
{
if ($db['Database'] == self::SESSIONDB)
{
mysql_select_db(self::SESSIONDB, self::$DB);
$this->SetTable();
return;
}
}
}
die ("Datenbank 'php5test' ist nicht vorhanden!");
}
## Eröffnung der Sitzung
function ms_open($sesspath, $sessname)
{
#echo "OPEN \$sesspath = $sesspath; \$sessname = $sessname<br />\n";
$time = time();
$sessid = session_id();
$query = "SELECT * FROM currentsession WHERE sessionID = '$sessid'";
$RS = mysql_query($query, self::$DB);
## Erneuern der aktuellen Sitzung, indem der Zeitstempel neu gesetzt wird
if (mysql_num_rows($RS) == 0)
{
$query = "INSERT INTO currentsession (sessionID, laccess)
VALUES ('$sessid', '$time')";
}
## Ist keine Sitzung vorhanden, wird ein neuer Datenbankeintrag erzeugt
else
{
$query = "UPDATE currentsession
SET laccess = '$time'
WHERE sessionID = '$sessid'";
}
$RS = mysql_query($query, self::$DB);
return $RS;
}
## Lesen der bereits in der Sitzung befindlichen Variablen
function ms_read($sessid)
{
#echo "READ \$sessid = $sessid;<br />\n";
$query = "SELECT *
FROM currentsession
WHERE sessionID='$sessid'";
$RS = mysql_query($query, self::$DB);
$arrRS = mysql_fetch_assoc($RS);
## Abruf des Felds "variables" in der Tabelle. Die Deserialisierung
## wird von PHP selbst erledigt
if (is_array($arrRS))
{
return $arrRS['variables'];
}
else
{
return FALSE;
}
}
## Sichern der in "$_SESSION" befindlichen Variablen. PHP bietet
## die Sitzungsvariablen bereits serialisiert an.
function ms_write($sessid, $varis)
{
#echo "WRITE \$sessid = $sessid; \$varis = $varis<br />\n";
$query = "UPDATE currentsession
SET variables = '$varis'
WHERE sessionID = '$sessid'";
$RS = mysql_query($query, self::$DB);
return (bool) $RS;
}
## Wenn eine Sitzung ausdrücklich oder durch Befehle zerstört wird,
## entfernt die Funktion "ms_destroy" den Eintrag aus der Datenbank.
function ms_destroy($sessid)
{
#echo "DESTROY \$sessid = $sessis;<br />\n";
$query = "DELETE FROM currentsession
WHERE sessionID = '$sessid'";
$RS = mysql_query($query, self::$DB);
return (bool) $RS;
}
## Aufruf der Garbage Collection je nach Einstellung der Parameter.
## Veraltete Sitzungen werden aus der Datenbank entfernt.
function ms_gc($sesslt)
{
#echo "GC \$sesslt = $sesslt;<br />\n";
$tStamp = time() - $sesslt;
$query = "DELETE FROM currentsession
WHERE laccess < '$tStamp'";
$RS = mysql_query($query, self::$DB);
return (bool) $RS;
}
## Schliessen der Sitzung, was zum Schliessen der Datenbank benutzt wird.
function ms_close()
{
#echo "CLOSE<br />\n";
mysql_close(self::$DB);
}
}
## Einmalige Instanziierung der Klasse "SessionManager"
new SessionManager();
?>
|
Das folgende Skript zeigt die Nutzung. Die Sitzungsfunktionen werden nach dem eigentlichen Skript aufgerufen. In der gezeigten Ausgabe sind die Zeitpunkte und die jeweils beteiligten Daten zu sehen.
<?php
## Name session_dbsesstest.php
include("./session_dbsess.php");
?>
<b>Seitenstart</b><br />
<?php
$sessid = session_id();
$x = 122;
$s = "Test";
$a = array(1, 22, "acht");
$_SESSION['x'] = $x;
echo "Die Sitzungs-ID: $sessid<br />\n";
$_SESSION['s'] = $s;
$_SESSION['a'] = $a;
?>
<a href="session_dbsessread.php">Auslesen auf anderer Seite</a><br />
<b>Seitenende</b><br />
|
Seitenstart |
Mit den oben erwähnten eingekommentierten "echo"-Befehlen sieht die Ausgabe wie folgt aus.
KONSTRUKTOR |
Zum Beweis, dass Daten von Seite zu Seite erhalten bleiben, dient hier das Skript "session_dbsessread.php".
<?php
## Name session_dbsessread.php
include("./session_dbsess.php");
?>
<b>Test</b><br />
<pre>
<?php
foreach ($_SESSION as $var => $val)
{
echo "\$$var = ";
var_export($val);
echo ";<br />";
}
?>
</pre>
<p><a href="session_dbsesstest.php">Zurück</a></p>
|
KONSTRUKTOR Zurück WRITE $sessid = 6e7c1295b62284cb359c73bcfc531694; $varis = |
Nach dem Klicken auf den Link "Zurück" zeigt die Ausgabe, dass die Daten vollständig wiederhergestellt werden konnten.
KONSTRUKTOR |