奇妙な問題に遭遇しました。Linux のセッション保存ハンドラーは正常に動作しません (ローカルの Windows プラットフォームでも同じコードが正常に動作します)。セッション保存ハンドラーのコードは次のとおりです。
<?php
class session
{
public static function init()
{
session_set_save_handler('session::open', 'session::close', 'session::read', 'session::write', 'session::destroy', 'session::gc');
}
public static function open($save_path, $session_name)
{
if (!is_dir($save_path)) {
mkdir($save_path, 0777);
}
return true;
}
public static function close()
{
return true;
}
public static function read($sid)
{
global $db, $user;
register_shutdown_function('session_write_close');
if (!isset($_COOKIE[session_name()])) {
$user = anonymousUser($sid);
return '';
}
$result = $db->query('SELECT s.data as session_data, s.* , u.* FROM users u INNER JOIN sessions s ON u.uid = s.uid WHERE s.sid = "' . $db->escape($sid) .
'" AND timestamp >= ' . $db->escape(TIMESTAMP - Bl_Config::get('session.lifetime', 10800)));
$user = $result->row();
if ($user) {
$data = $user->session_data;
unset($user->passwd, $user->session_data);
if ($user->uid > 0 && $user->status == 1) {
$userInstance = User_Model::getInstance();
$user->roles = $userInstance->getUserRoles($user->uid);
$user->roles[] = User_Model::ROLE_AUTHENTICATED_USER;
$user->permissions = array();
$user->data = (isset($user->data) && $user->data) ? unserialize($user->data) : array();
foreach ($user->roles as $rid) {
$user->permissions = array_merge($user->permissions, $userInstance->getRolePermissions($rid));
}
$user->permissions = array_unique($user->permissions);
} else {
$user = anonymousUser($sid);
}
return $data;
} else {
$user = anonymousUser($sid);
return '';
}
}
public static function write($sid, $data)
{
global $db, $user;
if (!isset($user) || ($user->uid == 0 && empty($_COOKIE[session_name()]) && empty($data))) {
return true;
}
$uri = '/' . Bl_Core::getUri();
$db->exec('UPDATE sessions SET uid = ' . $db->escape($user->uid) . ', ip = "' . $db->escape(ipAddress()) .
'", uri = "' . $db->escape($uri) . '", data = "' . $db->escape($data) . '", timestamp = ' .
$db->escape(TIMESTAMP) . ' WHERE sid = "' . $db->escape($sid) . '"');
if (!$db->affected()) {
$db->exec('INSERT IGNORE INTO sessions (sid, uid, ip, uri, data, timestamp) VALUES ("' . $db->escape($sid) .
'", ' . $db->escape($user->uid) . ', "' . $db->escape(ipAddress()) . '", "' . $db->escape($uri) . '", "' .
$db->escape($data) . '", ' . $db->escape(TIMESTAMP) . ')');
}
return true;
}
public static function destroy($sid)
{
global $db;
$db->exec('DELETE FROM sessions WHERE sid = "' . $db->escape($sid) . '"');
return true;
}
public static function gc($lifetime)
{
global $db;
$db->exec('DELETE FROM sessions WHERE timestamp < ' . $db->escape(TIMESTAMP - Bl_Config::get('session.lifetime', 10800)));
return true;
}
public static function count($timestamp = 0, $hasAnonymous = true)
{
global $db;
if (!$hasAnonymous) {
$cond = ' AND uid > 0';
} else {
$cond = '';
}
$result = $db->query('SELECT COUNT(0) FROM sessions WHERE timestamp > ' . $timestamp . $cond);
return $result->one();
}
}
セッション保存ハンドラを呼び出す方法は次のとおりです。
session::init();
session_start();
しかし、静的クラス セッションでメソッドが呼び出されませんでした。そして、 session_start() が呼び出された後、アプリが停止したようです。
私が使用した php のバージョンはPHP Version 5.1.6
.php.ini に関連しているのか、db の特権がこのような問題を引き起こしたのかわかりません。root db ユーザーを使用しており、接続は既に設定されています...
セッションのphp.ini設定は次のとおりです(Mike Purcellの提案に従って、session.save_pathを「/ var/lib/php/session」から「/ tmp」に変更しました):
session.save_handler = files
session.save_path = "/tmp"
session.use_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.bug_compat_42 = 0
session.bug_compat_warn = 1
session.referer_check =
session.entropy_length = 0
session.entropy_file =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
エラーメッセージは次のとおりです。
Fatal error: session_start() [<a href='function.session-start'>function.session-start</a>]: Failed to initialize storage module: user (path: /tmp)
助けてください、ありがとう!