我正在尝试使用session_set_save_handler将我的会话写入数据库,但我似乎无法使这些工作正常工作。
这是我的会话处理程序类:
<?php
require_once(__DIR__ .'/class.Database.php');
class MySessionHandler implements SessionHandlerInterface {
var $db;
var $maxlifetime;
function open($save_path, $name) {
$this->maxlifetime = get_cfg_var('session.gc.maxlifetime');
$this->db = new Database();
if(!$this->db) {
return false;
}
return true;
}
function close() {
return true;
}
function read($session_id) {
$result = $this->db->select('*', 'sessions')
->where(array('session_id' => array('=', $session_id)))
->run();
return (string)@$result[0]['sessions'];
}
function write($session_id, $session_data) {
$check_exists = $this->db->select('*', 'sessions')
->where(array('session_id' => array('=', $session_id)))
->run();
if($check_exists->num_rows >= 1) {
$this->db->update('sessions')
->set(array('session_id' => $session_id, 'session_data' => $session_data))
->where(array('session_id' => array('=', $session_id)))
->run();
} else {
$this->db->insert('sessions')
->values(array('session_id' => $session_id, 'session_data' => $session_data))
->run();
}
return true;
}
function destroy($session_id) {
$this->db->delete('session')
->where(array('session_id' => array('=', $session_id)))
->run();
}
function gc($lifetime) {
}
}
这是我的数据库类:
<?php
class Database {
protected $host;
protected $username;
protected $password;
protected $database;
private $build = NULL;
public function __construct() {
global $config;
$this->host = $config['db']['host'];
$this->username = $config['db']['username'];
$this->password = $config['db']['password'];
$this->database = $config['db']['database'];
$this->mysqli = new mysqli($this->host, $this->username, $this->password, $this->database);
}
public function select($columns = '*', $table) {
$this->build = 'SELECT ';
if(is_array($columns) == TRUE) {
$this->build .= implode(',', $columns);
} else {
$this->build .= $columns;
}
$this->build .= ' FROM `'. $table .'`';
return $this;
}
public function delete($table) {
$this->build = 'DELETE FROM `'. $table .'`';
return $this;
}
public function update($table) {
$this->build = 'UPDATE `'. $table .'`';
return $this;
}
public function insert($table) {
$this->build = 'INSERT INTO `'. $table .'`';
return $this;
}
public function values($data) {
$dataKeys = array_keys($data);
$dataValues = array_values($data);
$this->build .= ' ('. implode(',', $dataKeys) .') VALUES (';
$newValues = array();
foreach($dataValues as $value) {
$newValues[] = '\''. $value .'\'';
}
$this->build .= implode(',', $newValues) .')';
return $this;
}
public function set($data) {
$this->build .= ' SET ';
$dataArray = array();
foreach($data as $key => $value) {
$dataArray[] = '`'. $key .'`=\''. $value .'\'';
}
$this->build .= implode(',', $dataArray);
return $this;
}
public function where($data) {
$this->build .= ' WHERE ';
if(is_array($data) == TRUE) {
$dataKeys = array_keys($data);
$dataValues = array_values($data);
$i = 0;
foreach($dataValues as $value) {
if(empty($value[2]) == FALSE) {
$this->build .= $value[2] .' `'. $dataKeys[$i] .'` '. $value[0] .' \''. $value[1] .'\' ';
} else {
$this->build .= '`'. $dataKeys[$i] .'` '. $value[0] .' \''. $value[1] .'\' ';
}
++$i;
}
} else {
$this->build .= $data;
}
return $this;
}
public function orderBy($field, $dir) {
$this->build .= ' ORDER BY `'. $field .'` '. strtoupper($dir);
return $this;
}
public function limit($max, $min = '0') {
$this->build .= ' LIMIT '. $min .', '. $max;
return $this;
}
public function run() {
$query = $this->mysqli->query($this->build);
return $query;
}
}
我在配置文件中调用两个,我在索引页面中调用它,如下所示:
<?php
session_start();
$config['db']['host'] = 'localhost';
$config['db']['username'] = 'root';
$config['db']['password'] = 'password';
$config['db']['database'] = 'pizza';
$config['salt'] = 'randomsalt';
$classes = array('Database', 'MySessionHandler');
foreach($classes as $class) {
require_once(__DIR__ .'/class.'. $class .'.php');
}
$sessionHandler = new MySessionHandler();
session_set_save_handler(
array($sessionHandler, 'open'),
array($sessionHandler, 'close'),
array($sessionHandler, 'read'),
array($sessionHandler, 'write'),
array($sessionHandler, 'destroy'),
array($sessionHandler, 'gc')
);
register_shutdown_function('session_write_close');
但它不起作用。请问有人能协助我吗?
由于
答案 0 :(得分:1)
根据session_set_save_handler() Manual我认为,问题正在发生,因为在设置自定义处理程序之前,您正在使用session_start()
开始会话,因此更改不起作用。
在设置所有处理程序后启动会话尝试尝试。
好的,我已经测试了你提供的代码并发现了一些问题。
首先,如前所述,在设置所有处理程序后,您应该开始使用session_start()
进行会话。
辅助,从数据库中获取会话数据时遇到错误。我在MySessionHandler的代码中做了一些更改,发现它在以下情况下运行良好:
function read($session_id) {
$result = $this->db->select('*', 'sessions')
->where(array('session_id' => array('=', $session_id)))
->run();
if(!$result) {
// default value for empty session
return [];
} else {
// fetching data record
$record = $result->fetch_assoc()['session_data'];
}
// unserializing data record
return unserialize($record);
}
function write($session_id, $session_data) {
$check_exists = $this->db->select('*', 'sessions')
->where(array('session_id' => array('=', $session_id)))
->run();
if($check_exists->num_rows >= 1) {
// added serialization on save
$this->db->update('sessions')
->set(array('session_id' => $session_id, 'session_data' => serialize($session_data)))
->where(array('session_id' => array('=', $session_id)))
->run();
} else {
// added serialization on save
$this->db->insert('sessions')
->values(array('session_id' => $session_id, 'session_data' => serialize($session_data)))
->run();
}
return true;
}
您可以选择序列化的方式,但是应该序列化,因为会话通常是$_SESSION
变量上的数组。