這裏所有的答案似乎在說以明顯不打算使用會話方法的方式使用會話方法......即多次呼叫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