4

我有一个 session_id,我想读取它的数据而不将其加载到$_SESSION数组中。请记住,我并没有将我的问题局限于某个特定的会话处理程序。

[更新]

这是我的场景:

我有两个(或更多)不同的开源项目想要合并为一个。这些项目使用会话,但它们相互覆盖是可行的(因为它们都在同一个主机和同一个域中)。为了防止这种情况发生,我为每个人设置了不同的 session_names,这样他们就有了自己的会话。但是我需要编写一些胶水代码,我必须在其中访问两个会话。我可以加载一个,$_SESSION但我必须在不加载的情况下阅读其他内容。

[更新]

考虑到到目前为止给出的答案,我想进一步澄清一些事情。我寻找的解决方案是在同一个请求中启动会话两次(或更多)。并且每次都使用不同的 session_id。这样我就可以复制会话并加载另一个。话虽如此,这并不是唯一的解决方案,但它最接近我正在寻找的东西(只是一个提示)。

4

4 回答 4

5

我将一个一个地启动两个会话并将 $_SESSION 值存储在本地数组中。

IE

// Loading the first session.
session_name('first_session_name');
session_start();
// Now we have first session variables available in $_SESSION
$_FIRST_SESSION = $_SESSION;
// End current session.
session_write_close();
// Just to make sure nothing remains in the session.
unset($_SESSION);
// Now set the second session name.
session_name('second_session_name');
// Check and see if the second session name has a session id.
if (isset($_COOKIE['second_session_name']))
    // There's already a session id for this name.
    session_id($_COOKIE['second_session_name']);
else
    // We need to generate a new session id as this is the first time.
    session_id(sha1(mt_rand()));
session_start();
$_SECOND_SESSION = $_SESSION;
于 2013-06-24T10:42:38.107 回答
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);

如果您使用它,您的所有项目都会有一个大型会话。您无需更改任何内容(除了删除所有session_start().

我想您的每个项目都在自己的路径中,因此,要区分不同$_SESSION的 s,请使用:

$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 回答
0

如果您的项目在一台服务器上运行,您可以找到此会话存储在哪里,并尝试在不加载 PHP 实例的情况下手动读取它(php 只是一个示例)。例如,所有通过路径定位的 php 会话保存在 php.ini 中的 session.save_path 变量中。因此,您可以读取此变量(通过一些脚本 [bash?] 对其进行解析),然后将会话读取为公共文件。对于 perl,它取决于会话模块将在项目中使用什么。无论如何,最终它将是一些包含服务器文件系统中文件的文件夹。您需要为所有使用不同语言的项目制定自己的解析规则。

于 2013-06-23T19:26:37.607 回答