Question...
Is the
CI_Session_database_driver::destroy() called when the session is regenerated, as well as logout?
I took your advice, and created a table,
account_sessions_assoc, that has a unique automatically generated ID, which is the main point of reference, as well as
account_id and
session_id, when
MY_Session_database_driver::write() is called, it will execute
parent::write(), then it will execute another method,
Accounts_model::account_session_assoc(), that checks if the old session ID is in the
account_sessions_assoc table, if so, update the
account_sessions_assoc.session_id to the new
$session_id, if not, create a new record with the
$account_id and the
$session_id.
I created a
MY_Session_database_driver::destroy() which just executes
parent::destroy(), then executes a newly created
MY_Session_database_driver::_assoc_gc(), which will delete any records in the
account_sessions_assoc table if the current
account_sessions_assoc.session_id is NOT in the
ci_sessions table (This method is also executed by
MY_Session_database_driver::gc(), which just executes
parent::gc() then
_assoc_gc())
The problem im running into, is records are getting deleted out of the
account_sessions_assoc table, when sessions are still in
ci_sessions, and after viewing some logs, it looks like the
MY_Session_database_driver::destroy() method is being called when the
MY_Session:ess_regenerate() is being called.
If im right, and the
destroy() is being called when the session is regenerated (probably because
sess_regenerate_destroy = TRUE), then I need to somehow let the
MY_Session_database_driver::_assoc_gc() method know that the session is being regenerated, and not to delete it.
Thank you for the suggestion about creating a new table for associations, that was what I originally did, and should have stuck with that, definitely works better. Now just got this one last issue to take care of!
Thank you for the help!
Update: I added a column,
account_sessions_assoc.regens, which will start at 0, and +1 for every time a record is updated, I removed the reference to
self::assoc_gc() from
MY_Session_database_driver::destroy(), and the regens started climbing.. 1.. 2.. 3.. etc. Then I re-added the reference in
destroy() to
self::assoc_gc(), and the new records were all being added to the
account_sessions_assoc table, new ID's, session ID's and
regens are staying at 0.
So its definitive that
destroy() is being called when sessions are regenerated.
Since
MY_Session_database_driver::write() is what does all of the inserts/updates in
account_sessions_assoc, I believe what im running into is ironically the
EXACT same issue I had before I took your advice, which now, is...
1)
MY_Session:ess_regenerate() gets called, which updates the
account_sessions_assoc.session_id from the old session ID to the new session ID
2) Then
MY_Session_database_driver::destroy() gets called, which deletes the session_id from ci_sessions
3)
MY_Session_database_driver::destroy() calls
self::assoc_gc(), which will delete the record from
account_sessions_assoc, since
MY_Session_database_driver::write() has not been called to quickly create the new record.
If I can have
MY_Session_database_driver::destroy() realize its being called after
MY_Session:ess_regenerate(), then I can have it not execute
self::assoc_gc()
I tried doing this, but it doesnt seem to work:
PHP Code:
<?php
class MY_Session extends CI_Session
{
public static $sess_info = array(
'old' => NULL,
'new' => NULL
);
public function sess_regenerate( $destroy = FALSE )
{
self::$sess_info['old'] = session_id();
parent::sess_regenerate( $destroy );
self::$sess_info['new'] = session_id();
}
}
class MY_Session_database_driver extends CI_Session_database_driver
{
public function destroy( $session_id )
{
// Execute the real destroy first...
if( ! parent::destroy( $session_id ) )
{
return FALSE;
}
// Check if destroy() is being called after a regeneration, if so, just return true...
if( ! is_null( MY_Session::$sess_info['old'] ) AND ! is_null( MY_Session::$sess_info['new'] ) )
{
return TRUE;
}
// If not, clean up `account_sessions_assoc` based on whats in `ci_sessions`
else
{
return $this->_assoc_gc();
}
}
}
MY_Session::$sess_info['old'] and
MY_Session::$sess_info['old'] both start off as NULL, as set by the constructor, so it seems like they re getting set to null after
MY_Session:ess_regenerate(), but before
MY_Session_database_driver::destroy(), which is throwing me off a little...
P.S. Sorry for the overwhelming amount of info.. Im just trying to be as precise about whats happening as I can be. I think its also making the situation seem more complicated than it really is, which I hate doing.