当生命周期结束时,Zend Framework的哪个部分正在清理会话对象?

时间:2012-03-08 16:18:22

标签: php zend-framework session

我在Zend中有一个应用程序,我需要实现将用户工作时间记录到数据库的系统。有id_worktime,id_user,login_time和logout_time。登录和注销很容易,但是当用户没有比gc_maxlifetime做更长的时间时会出现问题。我编写了扩展Zend_Session_SaveHandler_DbTable的类,其中我重写了gc()方法:

class Vao_Session extends Zend_Session_SaveHandler_DbTable
{   
public function gc($maxlifetime)
{
    $garbage = $this->fetchAll($this->select()->from('session')->where('`modified` + `lifetime` < ?', time()));

    foreach ($garbage as $session)
    {
        $variables = array();
        $a = preg_split("/(\w+)\|/", $session['data'], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
        for($i = 0; $i < count($a); $i = $i + 2){
            $variables[$a[$i]] = unserialize($a[$i + 1]);
        }

        if (isset($variables['worktime']))
        {
            $worktime = $variables['worktime'];
            $idWorktime = $worktime['id_worktime'];

            if ($idWorktime)
            {
                $date = new Zend_Date($session['modified']);
                $data['logout_time'] = $date->toString(Zend_Date::ISO_8601);
                $worktimeTable = new Application_Model_DbTable_Worktime();
                $worktimeTable->update($data, 'id_worktime = '.$idWorktime);
            }
        }
    }

    parent::gc($maxlifetime);
}
}

当我从其他网络浏览器点击刷新时,它工作正常 - 会话表中的旧行被删除,logout_time在工作时间表中更新。但是当我在用户登录的Web浏览器中点击刷新(会话当然已过期)时,没有任何内容被放入工作时间并且会话中的行被更新 - 列'modified'被设置为当前时间并且'data'等于:

SessionPreferencesFlag|a:1:{s:16:"sessionSavedInDb";b:1;}

(之前有Zend_Auth对象和更多,其中包括我需要的id_worktime)。

现在问题 - Zend Framework的哪一部分清除会话行?我想这是Zend_Session中的东西,但我真的找不到它。请帮忙吗?

2 个答案:

答案 0 :(得分:1)

Zend_Session建立在内置的PHP会话功能之上,因此垃圾收集方法在适当的时候由PHP本身调用。

如果您查看Zend_Session_SaveHandler_DbTable的源代码,我认为您的问题是在read()方法中,如果它成功地从数据库中加载会话但发现它已过期,它调用destroy(),删除会话数据。这会“绕过”您通过删除会话时更新工作时间所需的代码。垃圾收集。我建议将大部分代码移到另一个从gc()调用的方法。然后,您还可以扩展destroy()方法,以使其也可以调用新方法。

答案 1 :(得分:1)

感谢Tim Fountain我设法解决了这个问题。工作代码:

class Vao_Session extends Zend_Session_SaveHandler_DbTable
{   
    public function read($id)
    {
        $return = '';

        $rows = call_user_func_array(array(&$this, 'find'), $this->_getPrimary($id));

        if (count($rows)) {
            if ($this->_getExpirationTime($row = $rows->current()) > time()) {
                $return = $row->{$this->_dataColumn};
            } else {
                $this->_saveLogoutTime($row);
                $this->destroy($id);
            }
        }

        return $return;
    }

    public function gc($maxlifetime)
    {
        $garbage = $this->fetchAll($this->select()->from('session')->where('`modified` + `lifetime` < ?', time()));

        foreach ($garbage as $session)
        {
            $this->_saveLogoutTime($session);
        }

        parent::gc($maxlifetime);
    }

    private function _saveLogoutTime($sessionRow)
    {
        $variables = array();
        $a = preg_split("/(\w+)\|/", $sessionRow[$this->_dataColumn], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
        for($i = 0; $i < count($a); $i = $i + 2){
            $variables[$a[$i]] = unserialize($a[$i + 1]);
        }

        if (isset($variables['worktime']))
        {
            $worktime = $variables['worktime'];
            $idWorktime = $worktime['id_worktime'];

            if ($idWorktime)
            {
                $data = array();
                $date = new Zend_Date($sessionRow[$this->_modifiedColumn]);
                $data['logout_time'] = $date->toString(Zend_Date::ISO_8601);
                $worktimeTable = new Application_Model_DbTable_Worktime();
                $worktimeTable->update($data, 'id_worktime = '.$idWorktime);
            }
        }
    }
}