这里所有的答案似乎在说以明显不打算使用会话方法的方式使用会话方法......即多次呼叫session_start()
。
PHP网站提供了一个示例SessionHandlerInterface实现,它将像现有会话一样工作,但不锁定文件。只是实现他们的示例接口修复了我的锁定问题,以允许在同一个会话上进行并发连接,而不会限制将会话添加到会话的能力。为了防止一些竞争条件,因为应用程序的会话不是完全无状态的,所以我必须设法在不中断请求的情况下保存会话,以便重要更改可以在更改后立即保存,不太重要的会话更改可以保存在请求结束时。见下面的例子为使用:
Session::start();
echo("<pre>Vars Stored in Session Were:\n");print_r($_SESSION);echo("</pre>");
$_SESSION['one'] = 'one';
$_SESSION['two'] = 'two';
//save won't close session and subsequent request will show 'three'
Session::save();
$_SESSION['three'] = 'three';
如果更换Session::start()
与session_start()
和Session::save()
与session_write_close()
,你会发现,后续请求将永远不会打印出的第三个变量...它将会丢失。但是,使用SessionHandler(下面),不会丢失任何数据。
OOP实现需要PHP 5.4+。但是,您可以在旧版本的PHP中提供单独的回调方法。 See docs。
namespace {
class Session implements SessionHandlerInterface {
/** @var Session */
private static $_instance;
private $savePath;
public static function start() {
if(empty(self::$_instance)) {
self::$_instance = new self();
session_set_save_handler(self::$_instance,true);
session_start();
}
}
public static function save() {
if(empty(self::$_instance)) {
throw new \Exception("You cannot save a session before starting the session");
}
self::$_instance->write(session_id(),session_encode());
}
public function open($savePath, $sessionName) {
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}
return true;
}
public function close() {
return true;
}
public function read($id) {
return (string)@file_get_contents("$this->savePath/sess_$id");
}
public function write($id, $data) {
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
public function destroy($id) {
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
}
return true;
}
public function gc($maxlifetime) {
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}
return true;
}
}
后知后觉,对未来的读者,我建议你使用'的session_set_save_handler()'为更多最佳实践,因为它不涉及任何变通办法,但修改会话作为PHP作者似乎有意。我已经发布了一个如何在下面执行此操作的示例。 – 2015-01-16 23:11:56