あなたが使用しているプロジェクトに隠れ$_SESSION
ます。プロジェクトは$_SESSION
以前と同じように単純に使用する必要がありますが、読み取るデータを管理します。また、独自のプロジェクトを使用してSessionHandler
、一方のプロジェクト$_SESSION
が破棄されても、他方のプロジェクトが破棄されないようにします。
このファイルは、セッションを開始するときに含める必要があります。次に、どこにも使用しないでくださいsession_start()
。
class SessionAccess implements ArrayAccess {
protected $handler;
public $session;
public function __construct (SharedSessionHandler $handler) {
$this->handler = $handler;
$this->session = $_SESSION;
if (!isset($this->session[NULL]))
$this->session[NULL] = [];
}
public function __get ($project) {
return $this->session[$project];
}
public function offsetGet ($id) {
return $this->getKey($id)[$id];
}
public function __set ($project, $val) {
$this->session[$project] = $val;
}
public function offsetSet ($id, $val) {
return $this->getKey($id)[$id] = $val;
}
public function __isset ($project) { // don't think it should be used with empty() ...
return isset($this->session[$project]);
}
public function offsetExists ($id) {
return isset($this->getKey($id)[$id]);
}
public function __unset ($project) {
$this->session[$project] = [];
}
public function offsetUnset ($id) {
unset($this->getKey($id)[$id]);
}
protected function &getKey ($id) {
return isset($this->session[NULL][$id])?$this->session[NULL]:$this->session[$this->handler->projectMapper()];
}
}
class SharedSessionHandler extends SessionHandler { // we want to preserve write/read functions etc., only put a thin layer of abstraction between
protected $projects = [];
private $writing = false;
private $tmpSessionStore;
public function registerProject ($project_name, $base) {
$this->projects[$base] = $project_name;
if (!isset($_SESSION->$project_name))
$_SESSION->$project_name = [];
}
public function projectMapper () {
$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2];
foreach ($this->projects as $base => $name) {
if (substr_compare(realpath($base), realpath($bt["file"]), 0, strlen($base)) === 0)
return $name;
}
return NULL;
}
public function write ($session_id, $session_data) {
if (!$this->writing) {
$this->writing = true;
$this->tmpSessionStore = $_SESSION;
$_SESSION = $_SESSION->session;
session_write_close();
} else {
parent::write($session_id, $session_data);
$_SESSION = $this->tmpSessionStore;
$this->writing = false;
}
}
public function close () { // as session_write_close() _will_ trigger this (prevent writing to closed stream)
return true;
}
public function destroy ($session_id) {
$key = $this->projectMapper();
if ($key === null) {
foreach ($this->projects as $project)
unset($_SESSION->$project);
} else {
unset($_SESSION->$key);
}
}
}
session_set_save_handler($sessionHandler = new SharedSessionHandler());
session_start();
$_SESSION = new SessionAccess($sessionHandler);
これを使用すると、すべてのプロジェクトに対して 1 つの大きなセッションができます。何も変更する必要はありません (すべての を削除する以外はsession_start()
)。
すべてのプロジェクトが独自のパスにあると思うので、異なる を区別するには$_SESSION
、次を使用します。
$sessionHandler->registerProject("projectName", __DIR__); // __DIR__ or the path to the project
他のセッションにアクセスするには、 を使用します$_SESSION->projectName[$variable]
。
登録されたディレクトリにないものはすべて、同じグローバル セッション ストレージを使用します。このグローバル ストレージにキーが設定されていない場合、ローカル ストレージからキーが取得されるか、失敗して通知が表示されます。