I have an application in Zend where I need to implement system which will log users work time to database. There is id_worktime, id_user, login_time and logout_time. Logging in and logging out is easy, but there is problem when user doesn’t do anything longer than gc_maxlifetime. I wrote class extending Zend_Session_SaveHandler_DbTable where i override gc() method:
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);
}
}
It works ok when I hit refresh from other web browser – old rows in session table are deleted and logout_time is updated in worktime table. But when I hit refresh in web browser where user was logged in (session is expired now of course) nothing is put into worktime and row in session is updated – column ‘modified’ is set to current time and ‘data’ is equal to:
SessionPreferencesFlag|a:1:{s:16:"sessionSavedInDb";b:1;}
(before there was Zend_Auth object and a lot more, among others id_worktime which i need).
And now THE question – what part of Zend Framework clears that session row? I suppose it’s something in Zend_Session, but I really can’t find it. Some help, please?
Zend_Sessionbuilds on the built-in PHP session functionality, so the garbage collection method is called by PHP itself where appropriate.If you take a look at the source code for
Zend_Session_SaveHandler_DbTable, I think your problem is that in theread()method there, if it successfully loads a session out of the DB but finds it has expired, it callsdestroy(), deleting the session data. This ‘bypasses’ the code you have to update the work time when sessions are deleted via. garbage collection. I’d suggest moving the bulk of your code to another method which you call fromgc(). You can then also extend thedestroy()method to get it to call the new method as well.