PHP错误从mysql数据库初始化会话数据

时间:2012-07-25 06:28:35

标签: php mysql session

我已将会话设置为保存在数据库中。我想在多个子域之间共享同一个会话,但似乎每个子域都会覆盖另一个子域的会话。

例如,我在一个子域中的会话中添加了一些变量,并且它们显示为oky,但是当我访问其他子域时,会话为空。

我使用的课程如下:

<?php

class Nip_Session
{

    protected $id;
    protected $_lifetime;
    protected $db;
    protected $table = 'session';

    public function __construct()
    {
        $this->db =  Nip_Registry::instance()->get('__DBROOT');

        $this->_lifetime = get_cfg_var("session.gc_maxlifetime");

        ini_set('session.save_handler', 'user');
        register_shutdown_function('session_write_close');

        $id = $this->checkRequestId();
        $this->setHandlers()->start($id);
    }

    /**
     * Restarts the session, with new optional session id
     *
     * @param string $id
     */
    public function reinitialize($id = false)
    {
        session_write_close();
        $this->setHandlers()->start($id);
    }

    /**
     * Starts the session, with optional session id
     *
     * @param string $id
     */
    protected function start($id = false)
    {
        if ($id) {
            session_id($id);
        }
        Nip_AutoLoader::instance()->isFatal(false);
        session_start();
        Nip_AutoLoader::instance()->isFatal(true);
    }

    /**
     * Overrides default session handling functions
     *
     * @return Session
     */
    protected function setHandlers()
    {
        session_set_save_handler(
            array($this, 'open'),
            array($this, 'close'),
            array($this, 'read'),
            array($this, 'write'),
            array($this, 'destroy'),
            array($this, 'gc')
        );

        return $this;
    }

    public function open()
    {
        return true;
    }

    public function close()
    {
        return true;
    }

    /**
     * Public method to return the session id
     * @todo implement a verification method ( ex: adding another validation string in the sessionID )
     * @return int
     */
    public function getId()
    {
        return session_id();
    }

    /**
     * Gets the session ID from REQUEST
     * @return int
     */
    public function checkRequestId()
    {
        if (isset($_REQUEST['session_id'])) {
            return $_REQUEST['session_id'];
        }

        return false;
    }

    /**
     * Fetches session entry from database
     *
     * @param string $id
     * @return mixed
     */
    public function read($id)
    {
        /* @var $result Nip_DBResult */
        $query = $this->db->newQuery('select');
        $query->from($this->table)
              ->where('id = ?', $id)
              ->where('expires > ?', time())
              ->limit(1);
        $result = $this->db->execute($query);

        $return = false;
        if ($result->numRows()) {
            $row = $result->fetchResult();
            $return = $this->decodeData($row['data']);
        }
        return $return;
    }

    /**
     * Stores the surrent session in the database
     *
     * @param string $id
     * @param mixed $data
     * @return int
     */
    public function write($id, $data)
    {
        $replace = array();
        $replace['id'] = $id;
        $replace['data'] = $this->encodeData($data);
        $replace['expires'] = time() + $this->_lifetime;

        $query = $this->db->newQuery('replace');
        $query->table($this->table)
              ->data($replace);
        $result = $this->db->execute($query);

        return $this->db->affectedRows();
    }

    /**
     * Destroys current session and deletes it's entry from the database
     *
     * @param string $id
     * @return int
     */
    public function destroy($id)
    {
        $query = $this->db->newQuery("delete");
        $query->table($this->table);
        $query->where('id = ?', $id);
        $query->limit(1);
        $query->execute();

        return $this->db->affectedRows();
    }

    /**
     * Garbage control. Called by PHP to remove expired entries from the database
     * @return int
     */
    public function gc()
    {
        $query = $this->db->newQuery("delete");
        $query->table($this->table);
        $query->where('expires <= ?', time());
        $query->execute();

        return $this->db->affectedRows();
    }

    /**
     * @param Nip_DB_Wrapper $db
     * @return Nip_Session
     */
    public function setDB($db)
    {
        $this->db = $db;
        return $this;
    }

    /**
     * @param int $lifetime
     * @return Nip_Session
     */
    public function setLifetime($lifetime)
    {
        if ($lifetime && is_numeric($lifetime)) {
            $this->_lifetime = $lifetime;
        }
        return $this;
    }

    /**
     * Encodes data to be stored
     *
     * @param mixed $data
     * @return string
     */
    protected function encodeData($data)
    {
        return base64_encode($data);
    }

    /**
     * Decodes data to be used
     *
     * @param string $data
     * @return mixed
     */
    protected function decodeData($data)
    {
        return base64_decode($data);
    }

    /**
     * Singleton
     *
     * @return Nip_Session
     */
    static public function instance()
    {
        static $instance;
        if (!($instance instanceof Nip_Session)) {
            $instance = new Nip_Session();
        }
        return $instance;
    }

}

我做了一些回音,会话ID是一样的。我在read方法中做了一个var_dump,它似乎从数据库中读取了oky:

string(1484)"X3pJX1JQTk9LeW9fQVBBWk03dnhNMVFKNmxLZk1YdEtIMkNGS3EzdW5Oa0hvUFVaWTZJdHlyMzJUc09MUDUwUFpBZHZXTDZfbzM3SjhSbmp1T3lfVnBkMEdSY0dqQzc ......"

$ _SESSION仍为空:( 任何想法?谢谢你的帮助

2 个答案:

答案 0 :(得分:0)

会话ID默认存储在cookie中,因此不能在不同的域之间共享。我不确定是否将其设置为在网址中传播会产生影响

答案 1 :(得分:0)

来自suhosin的问题似乎是使用包含子域文档根的密钥对会话进行编码的问题。 suhosin.session.cryptdocroot 设置。

http://rommelsantor.com/clog/2011/02/06/php-shared-session-encoding-solution/