Какая часть Zend Framework очищает объект сеанса, когда время жизни истекло? - PullRequest
1 голос
/ 08 марта 2012

У меня есть приложение в 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 обновляется в таблице рабочего времени. Но когда я нажимаю «Обновить» в веб-браузере, где пользователь вошел в систему (сеанс, конечно, сейчас истек), ничто не добавляется в рабочее время, а строка в сеансе обновляется - столбец «измененный» устанавливается на текущее время, а «данные» равны

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

(до того, как появился объект Zend_Auth и многое другое, в том числе id_worktime, который мне нужен).

А теперь вопрос - какая часть Zend Framework очищает эту строку сеанса? Я предполагаю, что это что-то в Zend_Session, но я действительно не могу найти это. Помогите, пожалуйста?

Ответы [ 2 ]

1 голос
/ 09 марта 2012

Благодаря Тиму Фонтану мне удалось решить эту проблему. Рабочий код:

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);
            }
        }
    }
}
1 голос
/ 08 марта 2012

Zend_Session основывается на встроенной функциональности сеанса PHP, поэтому метод сборки мусора вызывается самим PHP, где это необходимо.

Если вы посмотрите на исходный код для Zend_Session_SaveHandler_DbTable, я думаю, что ваша проблема в том, что в методе read(), если он успешно загружает сеанс из БД, но обнаруживает, что он истекон вызывает destroy(), удаляя данные сеанса.Это «обходит» код, который вы должны обновить время работы, когда сеансы удаляются через.вывоз мусора.Я бы предложил перенести основную часть вашего кода в другой метод, который вы вызываете из gc().Затем можно также расширить метод destroy(), чтобы он также вызывал новый метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...