4

$_SESSION私は session_id を持っていて、配列にロードせずにそのデータを読みたいと思っています。質問を特定のセッション ハンドラに限定したわけではないことに注意してください。

[アップデート]

これが私のシナリオです:

1 つにマージしたい 2 つ (またはそれ以上) の異なるオープン ソース プロジェクトがあります。これらのプロジェクトはセッションを利用しますが、互いに上書きする可能性があります (すべて同じホストおよび同じドメインにあるため)。これが起こらないようにするために、それぞれに異なる session_names を設定して、独自のセッションを持つようにしています。しかし、両方のセッションにアクセスする必要があるグルー コードを作成する必要があります。1 つをロードできますが、ロード$_SESSIONせずに他のものを読まなければなりません。

[アップデート]

これまでの回答を踏まえて、もう少し明確にしようと思いました。私が探している解決策は、同じリクエスト内でセッションを 2 回 (またはそれ以上) 開始することです。そして、毎回異なる session_id を使用します。そうすれば、セッションのコピーを作成して、別のセッションをロードできます。そうは言っても、唯一の解決策である必要はありませんが、私が探しているものに最も近いものです(単なるヒントです)。

4

4 に答える 4

2

あなたが使用しているプロジェクトに隠れ$_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]

登録されたディレクトリにないものはすべて、同じグローバル セッション ストレージを使用します。このグローバル ストレージにキーが設定されていない場合、ローカル ストレージからキーが取得されるか、失敗して通知が表示されます。

于 2013-06-23T16:28:34.440 に答える
0

SessionHandler クラスとそのメソッドを使用しread($session_id)ます。

詳細はこちら: http://www.php.net/manual/en/class.sessionhandler.php

于 2013-06-20T07:43:51.913 に答える