【问题标题】:PHP: Session stored in database not always updatedPHP:存储在数据库中的会话并不总是更新
【发布时间】:2011-11-17 08:12:22
【问题描述】:

在数据库中存储会话时,我注意到更新会话不一定会调用 session_set_save_handler() 中设置的写入函数。当您在脚本末尾调用 session_write_close() 时,这个问题似乎得到了解决。

使用 session_set_save_handler() 将会话存储在数据库中时,我是否遗漏了什么?

我当前使用的代码。

// EXECUTE AT START OF SCRIPT
$session = new Session();
session_start();

会话类

public function __construct() {
    $database       = Database::instance();
    $this->dbh      = $database->dbh();
    $this->lifetime = get_cfg_var('session.gc_maxlifetime');

    session_set_save_handler(
        array(&$this, 'open'),
        array(&$this, 'close'),
        array(&$this, 'read'),
        array(&$this, 'write'),
        array(&$this, 'destroy'),
        array(&$this, 'clean')
    );
}

// SESSION HANDLER METHODS
function open($savePath, $sessionName) {
    return true;
}

function close() {
    return true;
}

function read($sessionUuid) {
    logMessage('READ SESSION DATA > ' . $sessionUuid);
    $data = array();
    $time = time();

    $sth = $this->dbh->prepare("SELECT sessionData FROM phpSession WHERE sessionUuid = :sessionUuid AND expires > " . $time);
    $sth->setFetchMode(PDO::FETCH_ASSOC);

    try {
        $sth->execute(array('sessionUuid' => $sessionUuid));

        if ($sth->rowCount() == 1) {
            $row = $sth->fetch();
            $data = $row['sessionData'];
        }

    } catch (PDOException $exception) {
        // HANDLE EXCEPTION
    }

    return $data;
}

function write($sessionUuid, $sessionData) {
    logMessage('WRITE SESSION DATA > ' . $sessionUuid);
    $time = time() + $this->lifetime;

    $sth1 = $this->dbh->prepare("SELECT sessionUuid FROM phpSession WHERE sessionUuid = :sessionUuid");

    try {
        $sth1->execute(array('sessionUuid' => $sessionUuid));

        $query  = '';
        $data   = array(
            'sessionUuid'   => $sessionUuid,
            'sessionData'   => $sessionData,
            'expires'       => $time
        );

        if ($sth1->rowCount() == 1) {
            // UPDATE
            $query = "UPDATE phpSession SET sessionUuid = :sessionUuid, sessionData = :sessionData, expires = :expires";

        } else {
            // INSERT
            $query = "INSERT INTO phpSession (sessionUuid, sessionData, expires) VALUES (:sessionUuid, :sessionData, :expires)";
        }

        $sth2 = $this->dbh->prepare($query);

        try {
            $sth2->execute($data);

        } catch (PDOException $exception) {
            // HANDLE EXCEPTION
        }

    } catch (PDOException $exception) {
        // HANDLE EXCEPTION
    }

    return true;
}

function destroy($sessionUuid) {
    $sth = $this->dbh->prepare("DELETE FROM phpSession WHERE 'sessionUuid' = :sessionUuid");

    try {
        $sth->execute(array('sessionUuid' => $sessionUuid));

    } catch (PDOException $exception) {
        // HANDLE EXCEPTION
    }

    return true;
}

function clean() {
    $sth = $this->dbh->prepare("DELETE FROM phpSession WHERE 'expires' < UNIX_TIMESTAMP()");

    try {
        $sth->execute();

    } catch (PDOException $exception) {
        // HANDLE EXCEPTION
    }

    return true;
}

【问题讨论】:

  • 只是对您的班级的一个小提示,而不是问题(您有答案):在最后两种方法(销毁和清理)中,我看到您将列名包含在查询之间撇号而不是反引号。这对你有用吗?
  • 感谢您的评论。到目前为止,我没有遇到任何使用撇号的问题。
  • 我不记得这条评论,但我仍然觉得奇怪的是,您在列名中使用了撇号。取这两个样本:codepad.org/n7mOQz5hcodepad.org/NeY7a7nn 第一个来自您的 destroy 方法,第二个用反引号替换撇号。第一个(您的)会将字符串“sessionUuid”与会话 ID 进行比较,并且始终为假。第二个会将该列的值与参数进行比较,有时会匹配行。您可以运行测试,您将看到使用您的查询没有删除任何记录

标签: php database session


【解决方案1】:

根据http://php.net/manual/en/function.session-write-close.php

会话数据通常在脚本终止后存储,无需调用 session_write_close(),但由于会话数据被锁定以防止并发写入,任何时候只有一个脚本可以对会话进行操作。

锁定通常是没有编写会话的原因。这可能发生在框架页面(如文档所述)或同时发生多个请求的冗长 ajax 请求中。

【讨论】:

    【解决方案2】:

    对于 PHP session_write_close() 作为关闭函数,以便在脚本执行周期结束之前进行数据库写入。

    register_shutdown_function('session_write_close');
    

    【讨论】:

      猜你喜欢
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 2022-07-01
      • 2011-02-14
      相关资源
      最近更新 更多