Permalink
Browse files

Added option to call sess_write() manually (in _output), which will p…

…revent it being called in __destruct()
  • Loading branch information...
1 parent 558e3ce commit 6bfedb25485ba8f8f0eb38a40a7b22ba1a6008c6 @danmontgomery committed Jan 27, 2012
View
14 core/MY_Controller.php
@@ -1,14 +0,0 @@
-<?php
-
-class MY_Controller extends CI_Controller {
-
- public function _output($output)
- {
- if(isset($this->session) && method_exists($this->session, 'sess_write'))
- {
- $this->session->sess_write();
- }
- echo $output;
- }
-
-}
View
38 libraries/Session.php
@@ -44,6 +44,7 @@ class Session extends CI_Driver_Library {
public $sess_match_useragent = TRUE;
public $sess_time_to_update = 300;
+ protected $_has_written = FALSE;
protected $_driver;
protected $valid_drivers;
@@ -119,6 +120,17 @@ public function __construct($params = array())
// --------------------------------------------------------------------
/**
+ * If session wasn't written by _output, try writing it here
+ */
+ public function __destruct()
+ {
+ if(method_exists($this, 'sess_write'))
+ $this->sess_write();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Serialize an array
*
* This function first converts any slashes found in the array to a temporary
@@ -395,6 +407,32 @@ public function _get_time()
// ------------------------------------------------------------------------
/**
+ * This session has already been written, don't try to write again
+ *
+ * @access public
+ * @return null
+ */
+ public function track_write()
+ {
+ $this->_has_written = TRUE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Check if session was written (presumably by _output, or manually)
+ *
+ * @access public
+ * @return bool
+ */
+ public function check_write()
+ {
+ return ( ! $this->_has_written );
@markhuot
markhuot Apr 24, 2012

I don't believe this should be negated. All your drivers run if ( ! $this->check_write()) meaning they're looking for TRUE if it has been written and FALSE if it has not. By negating it you're returning FALSE if it has been written and TRUE if it has not. I'll submit a pull request shortly.

+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Call child methods when they don't exist here
*
* @access public
View
10 libraries/session/Session_cache.php
@@ -133,8 +133,14 @@ public function sess_read()
*/
public function sess_write()
{
- $this->CI->cache->save($this->sess_id, $this->parent->_serialize($this->parent->userdata), $this->parent->sess_expiration);
- $this->_set_cookie();
+ if( ! $this->parent->check_write())
+ {
+ $this->CI->cache->save($this->sess_id, $this->parent->_serialize($this->parent->userdata), $this->parent->sess_expiration);
+
+ $this->parent->track_write();
+
+ $this->_set_cookie();
+ }
}
// --------------------------------------------------------------------
View
7 libraries/session/Session_cookie.php
@@ -120,7 +120,12 @@ public function sess_read()
*/
public function sess_write()
{
- $this->_set_cookie();
+ if( ! $this->parent->check_write())
+ {
+ $this->parent->track_write();
+
+ $this->_set_cookie();
+ }
}
// --------------------------------------------------------------------
View
63 libraries/session/Session_database.php
@@ -161,39 +161,44 @@ public function sess_read()
*/
public function sess_write()
{
- // set the custom userdata, the session data we will set in a second
- $custom_userdata = $this->parent->userdata;
- $cookie_userdata = array();
-
- // Before continuing, we need to determine if there is any custom data to deal with.
- // Let's determine this by removing the default indexes to see if there's anything left in the array
- // and set the session data while we're at it
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
+ if( ! $this->parent->check_write())
{
- unset($custom_userdata[$val]);
- $cookie_userdata[$val] = $this->parent->userdata[$val];
- }
+ // set the custom userdata, the session data we will set in a second
+ $custom_userdata = $this->parent->userdata;
+ $cookie_userdata = array();
+
+ // Before continuing, we need to determine if there is any custom data to deal with.
+ // Let's determine this by removing the default indexes to see if there's anything left in the array
+ // and set the session data while we're at it
+ foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
+ {
+ unset($custom_userdata[$val]);
+ $cookie_userdata[$val] = $this->parent->userdata[$val];
+ }
- // Did we find any custom data? If not, we turn the empty array into a string
- // since there's no reason to serialize and store an empty array in the DB
- if (count($custom_userdata) === 0)
- {
- $custom_userdata = '';
- }
- else
- {
- // Serialize the custom data array so we can store it
- $custom_userdata = $this->parent->_serialize($custom_userdata);
- }
+ // Did we find any custom data? If not, we turn the empty array into a string
+ // since there's no reason to serialize and store an empty array in the DB
+ if (count($custom_userdata) === 0)
+ {
+ $custom_userdata = '';
+ }
+ else
+ {
+ // Serialize the custom data array so we can store it
+ $custom_userdata = $this->parent->_serialize($custom_userdata);
+ }
+
+ // Run the update query
+ $this->CI->db->where('session_id', $this->parent->userdata['session_id']);
+ $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->parent->userdata['last_activity'], 'user_data' => $custom_userdata));
- // Run the update query
- $this->CI->db->where('session_id', $this->parent->userdata['session_id']);
- $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->parent->userdata['last_activity'], 'user_data' => $custom_userdata));
+ $this->parent->track_write();
- // Write the cookie. Notice that we manually pass the cookie data array to the
- // _set_cookie() function. Normally that function will store $this->userdata, but
- // in this case that array contains custom data, which we do not want in the cookie.
- $this->_set_cookie($cookie_userdata);
+ // Write the cookie. Notice that we manually pass the cookie data array to the
+ // _set_cookie() function. Normally that function will store $this->userdata, but
+ // in this case that array contains custom data, which we do not want in the cookie.
+ $this->_set_cookie($cookie_userdata);
+ }
}
// --------------------------------------------------------------------
View
11 libraries/session/Session_native.php
@@ -69,10 +69,15 @@ public function sess_read()
*/
public function sess_write()
{
- $_SESSION = array();
- foreach($this->parent->userdata as $key => $val)
+ if( ! $this->parent->check_write())
{
- $_SESSION[$key] = $val;
+ $_SESSION = array();
+ foreach($this->parent->userdata as $key => $val)
+ {
+ $_SESSION[$key] = $val;
+ }
+
+ $this->parent->track_write();
}
}
View
14 readme.md
@@ -17,4 +17,16 @@ There are a couple of new config options in config/session.php, and the 'sess_us
(Replace X.X.X with the appropriate version)
###NOTE
-I moved sess_write() to __destruct(), which means that session writes will only happen once per request (useful for database sessions), it also means that these queries won't show up in the profiler, because they happen after the profiler has finished running.
+I suggest adding a call to sess_write() in the _output function of the controller, which will write the session before output and avoid issues with setting the cookie. If you don't do this, the library will try to write in __destruct(), which may or may not cause you issues.
+
+ class MY_Controller extends CI_Controller {
+ public function _output($output)
+ {
+ if(isset($this->session))
+ {
+ $this->session->sess_write();
+ }
+
+ echo $output;
+ }
+ }

0 comments on commit 6bfedb2

Please sign in to comment.