在第二页

时间:2016-01-10 00:22:20

标签: php mysql session

我编写了一个类来将会话数据存储到我的数据库中(见下文)。登录后,一切正常,第一页加载,我看到数据库中的数据。

但是,继续下一页,print_r($ _ SESSION)返回一个空数组,并且数据库条目已更新,将数据列设置为空,但相应地更新了访问列。

编辑:要确认,正在更新具有现有会话ID的行,因为访问列具有新的时间值,但数据字段不是空白。

任何帮助非常感谢。感谢。

<?php
namespace MyCompany\MyProject;

use \PDO;


class Session
{
    private $dblayer;
    private $user_agent;

    public function __construct(PDO $dblayer)
    {
        $this->dblayer = $dblayer;
        $this->user_agent = $_SERVER['HTTP_USER_AGENT'];

        session_set_save_handler(
            array($this, 'open'),
            array($this, 'close'),
            array($this, 'read'),
            array($this, 'write'),
            array($this, 'destroy'),
            array($this, 'gc')
        );

        if ('LIVE' == DEVELOPMENT_MODE) {
            session_set_cookie_params(0, '/', '', true, true);
        } else {
            session_set_cookie_params(0, '/', '', false, true);
        }

        session_start();

    }

    public function checkUserAgent()
    {
        if ($_SERVER['HTTP_USER_AGENT'] === $this->user_agent) {
            session_regenerate_id(true);
            return true;
        }

        return false;
    }

    public function open()
    {
        if ($this->dblayer) {
            return true;
        }

        return false;
    }

    public function close()
    {
        $this->dblayer = null;
        if (!$this->dblayer) {
            return true;
        }

        return false;
    }

    public function read($id)
    {
        try {
            $this->dblayer->beginTransaction();
            $stmt = $this->dblayer->prepare("SELECT data FROM sessions WHERE id = :id LIMIT 1");
            $stmt->execute();

            $this->dblayer->commit();

            if ($data = $stmt->fetch()) {
                return $data['data'];
            }

            return '';

        } catch (\Exception $e) {
            $this->dblayer->rollBack();
            // will use file_put_contents to save error message, file etc to error log
            return false;
        }
    }

    public function write($id, $data)
    {

            $this->dblayer->beginTransaction();
            $stmt = $this->dblayer->prepare("REPLACE INTO sessions VALUES(:id, :data, NOW())");
            $stmt->bindParam(':data', $data);
            $stmt->bindParam(':id', $id);
            $stmt->execute();

            $this->dblayer->commit();

            if ($stmt) {
                return true;
            }

            $this->dblayer->rollBack();
            // can i save to error log here?
            return false;

    }

    public function destroy($id)
    {
        try {
            $this->dblayer->beginTransaction();
            $stmt = $this->dblayer->prepare("DELETE FROM sessions WHERE id = :id");
            $stmt->bindParam(':id', $id);
            $stmt->execute();

            $this->dblayer->commit();

        } catch (\PDOException $e) {
            $this->dblayer->rollBack();
            // again, will save error data to log
            echo $e->getMessage();
            return false;
        }
    }

    public function gc($max)
    {
        $to_delete = UNIX_TIMESTAMP(time() - $max);

        try {
            $this->dblayer->beginTransaction();
            $stmt = $this->dblayer->prepare("DELETE FROM sessions WHERE access < :to_delete");
            $stmt->bindParam(':to_delete', $to_delete);

            $this->dblayer->commit();

            return true;

        } catch (\PDOException $e) {
            $this->dblayer->rollBack();
            // save error data to log;
            return false;
        }
    }


}

3 个答案:

答案 0 :(得分:0)

在调用第二页时检查Session是否存在,如果不是,则调用session_start。

答案 1 :(得分:0)

在第二页上,确保放置session_start(); ,只需仔细检查,你可能会忽略。

答案 2 :(得分:0)

虽然大多数类似案例不太可能具有我所做的确切原因,但问题确实强调需要了解何时以及如何调用每个会话方法。问题实际上是在read()方法中,我没有绑定id参数。

缺少一行:

$stmt->bindParam(':id', $id);

所以任何人都有同样的问题,请检查所有方法!