Dieser Artikel stellt das Speichern von Sitzungen in einer PHP-Datenbank vor und kann auch als Referenz für Freunde in Not dienen.
Standardmäßig speichert PHP alle Sitzungsdaten in Textdateien auf dem Server. Diese Dateien werden normalerweise im temporären Verzeichnis gespeichert.
Warum müssen wir dann die Sitzung in der Datenbank speichern?
Der Hauptgrund: die Sicherheit des Systems zu verbessern. Auf einem gemeinsam genutzten Server verwenden alle Websites ohne besondere Einstellungen dasselbe temporäre Verzeichnis, was bedeutet, dass Dutzende Programme Dateien am selben Ort lesen und schreiben. Es wurde nicht nur die Geschwindigkeit verringert, sondern es war auch möglich, dass jemand anderes die Benutzerdaten meiner Website stehlen konnte.
Das Speichern von Sitzungsdaten in der Datenbank kann auch die Suche nach weiteren Informationen zu Website-Sitzungen erleichtern. Wir können die Anzahl der aktiven Sitzungen (die Anzahl der Benutzer, die gleichzeitig online sind) abfragen Zeit) und auch Sitzungsdaten werden gesichert.
Wenn meine Website gleichzeitig auf mehreren Servern läuft, kann ein Benutzer während einer Sitzung mehrere Anfragen an verschiedene Server senden, wenn die Sitzungsdaten jedoch auf einem bestimmten Server gespeichert werden Andere Server können diese Sitzungsdaten nicht nutzen. Wenn einer meiner Server nur die Rolle einer Datenbank übernimmt, wäre es für Sie dann nicht sehr praktisch, alle Sitzungsdaten in der Datenbank zu speichern?
Weitere Informationen zu PHP-Sitzungen finden Sie in diesem Blog. Erfahren Sie mehr über den SESSION-Mechanismus von PHP
Da die Sitzungsdaten auf dem Server und ein Index (Sitzungs-ID) auf dem Client gespeichert werden, entspricht dieser Index einem bestimmten Teil der Sitzungsdaten auf dem Server. Daher müssen die beiden Felder „id“ und „data“ in der Tabelle enthalten sein, und die Sitzung hat eine Ablaufzeit. Daher gibt es hier ein weiteres Feld mit dem Namen „last_accessed“. Hier habe ich die Tabelle unter der Testdatenbank erstellt:
CREATE TABLE sessions( id CHAR(32) NOT NULL, data TEXT, last_accessed TIMESTAMP NOT NULL, PRIMARY KEY(id) );
PS: Wenn das Programm eine große Datenmenge in der Sitzung speichern muss, muss das Datenfeld möglicherweise als MEDIUMTEXT- oder LONGTEXT-Typ definiert werden.
这里我们主要有两个步骤:
定义与数据库交互的函数
使PHP能使用这些自定义函数
在第二步中,是通过调用函数 session_set_save_handler()来完成的,调用它需要6个参数,分别是 open(启动会话)、close(关闭会话)、read(读取会话)、write(写入会话)、destroy(销毁会话)、clean(垃圾回收)。
我们新建php文件 sessions.inc.php ,代码如下:
<?php$sdbc = null; //数据库连接句柄,在后面的函数里面让它成为全局变量//启动会话function open_session(){ global $sdbc; //使用全局的$sdbc $sdbc = mysqli_connect('localhost', 'root', 'lsgogroup', 'test'); //数据库 test if (!$sdbc) { return false; } return true; }//关闭会话function close_session(){ global $sdbc; return mysqli_close($sdbc); }//读取会话数据function read_session($sid){ global $sdbc; $sql = sprintf("SELECT data FROM sessions WHERE id='%s'", mysqli_real_escape_string($sdbc, $sid)); $res = mysqli_query($sdbc, $sql); if (mysqli_num_rows($res) == 1) { list($data) = mysqli_fetch_array($res, MYSQLI_NUM); return $data; } else { return ''; } }//写入会话数据function write_session($sid, $data){ global $sdbc; $sql = sprintf("INSERT INTO sessions(id,data,last_accessed) VALUES('%s','%s','%s')", mysqli_real_escape_string($sdbc, $sid), mysqli_real_escape_string($sdbc, $data), date("Y-m-d H:i:s", time())); $res = mysqli_query($sdbc, $sql); if (!$res) { return false; } return true; }//销毁会话数据function destroy_session($sid){ global $sdbc; $sql = sprintf("DELETE FROM sessions WHERE id='%s'", mysqli_real_escape_string($sdbc, $sid)); $res = mysqli_query($sdbc, $sql); $_SESSION = array(); if (!mysqli_affected_rows($sdbc) == 0) { return false; } return true; }//执行垃圾回收(删除旧的会话数据)function clean_session($expire){ global $sdbc; $sql = sprintf("DELETE FROM sessions WHERE DATE_ADD(last_accessed,INTERVAL %d SECOND)<NOW()", (int)$expire); $res = mysqli_query($sdbc, $sql); if (!$res) { return false; } return true; }//告诉PHP使用会话处理函数session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'clean_session');//启动会话,该函数必须在session_set_save_handler()函数后调用,不然我们所定义的函数就没法起作用了。session_start();//由于该文件被包含在需要使用会话的php文件里面,因此不会为其添加PHP结束标签
PS:
处理“读取”函数外,其他函数必须返回一个布尔值,“读取”函数必须返回一个字符串。
.每次会话启动时,“打开”和“读取”函数将会立即被调用。当“读取”函数被调用的时候,可能会发生垃圾回收过程。
当脚本结束时,“写入”函数就会被调用,然后就是“关闭”函数,除非会话被销毁了,而这种情况下,“写入”函数不会被调用。但是,在“关闭”函数之后,“销毁”函数将会被调用。
.session_set_save_handler()函数参数顺序不能更改,因为它们一一对应 open 、close、read、、、、
会话数据最后将会以数据序列化的方式保存在数据库中。
使用新会话处理程序只是调用session_set_save_handler()函数,使我们的自定义函数能够被自动调用而已。其他关于会话的操作都没有发生变化(以前怎么用现在怎么用,我们的函数会在后台自动被调用),包括在会话中存储数据,访问保存的会话数据以及销毁数据。
在这里,我们新建 sessions.php 文件,该脚本将在没有会话信息时创建一些会话数据,并显示所有的会话数据,在用户点击 ‘log out’(注销)时销毁会话数据。
代码:
<?php//引入sessions.inc.php文件,即上面的代码require('sessions.inc.php');?><!doctype html><html lang='en'><head> <meta charset="utf-8"> <title>DB session test</title></head><body><?php//创建会话数据if(empty($_SESSION)){ $_SESSION['blah'] = "umlaut"; $_SESSION['this'] = 12345; $_SESSION['that'] = 'blue'; echo "<p>Session data stored</p>"; }else{ echo "<p>Session data exists:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">".print_r($_SESSION,1)."
session destroyed
"; }else{ echo "log out"; }echo "session data :
".print_r($_SESSION,1)."