Destramic Posted August 14, 2015 Share Posted August 14, 2015 hey guys i'm using the session_set_save_handler() function but when trying to write to a session i no longer have a connection to my database... public function initialize_session_handler() { $registry = new Registry; $db = $registry->db; $session_handler = new Session_DB_Handler; $session_handler->set_db_adapter($db); $session_handler->set_lifetime(1); print_r($session_handler); // property $_db stats mysqli connection session_set_save_handler( array($session_handler, 'open'), array($session_handler, 'close'), array($session_handler, 'read'), array($session_handler, 'write'), array($session_handler, 'destroy'), array($session_handler, 'clean') ); } when print_r($session_handler) it shows the class property $_db has a mysqli connection: Session\Session_DB_Handler Object ( [_db:protected] => DB\Driver\MySQLi Object ( [_identifier:protected] => mysqli Object ( [affected_rows] => 0 [client_info] => mysqlnd 5.0.11-dev - ********* - $Id: *********** $ [client_version] => 50011 [connect_errno] => 0 [connect_error] => [errno] => 0 [error] => [error_list] => Array ( ) [field_count] => 0 [host_info] => Localhost via UNIX socket [info] => [insert_id] => 0 [server_info] => 5.5.5-10.0.20-MariaDB [server_version] => 50505 [stat] => Uptime: 120613 Threads: 1 Questions: 73251 Slow queries: 0 Opens: 1606 Flush tables: 1 Open tables: 400 Queries per second avg: 0.607 [sqlstate] => 00000 [protocol_version] => 10 [thread_id] => 3215 [warning_count] => 0 ) [_config:protected] => Array ( [host] => localhost [username] => user [password] => pass ) [_table:protected] => [_result:protected] => [_statements:protected] => Array ( ) [_database:protected] => ) [_lifetime:protected] => 86400 ) but if i try to write to a session after initializing the session handler $_db property is null in my session handler class...i've also tried to use $_db as a static property...i just can't understand why it's null when I'm trying to write does anyone have any ideas as to why please? thank you Quote Link to comment Share on other sites More sharing options...
requinix Posted August 15, 2015 Share Posted August 15, 2015 And the code for Session_DB_Handler would be... Quote Link to comment Share on other sites More sharing options...
Destramic Posted August 15, 2015 Author Share Posted August 15, 2015 here's the session handler: the connection to the database is done before everything on my site and closes last...ensuring there is only one connection <?php namespace Session; class Session_DB_Handler { protected $_db; protected $_lifetime; public function __construct($config = array()) { ini_set('session.cookie_lifetime', 0); ini_set('session.gc_maxlifetime', 3600); ini_set('session.gc_probability', 1); ini_set('session.gc_divisor', 1000); session_set_cookie_params(0, '/', $_SERVER['HTTP_HOST'], false, true); session_name('SESSION_ID'); } public function open($session_path, $session_name) { return true; } public function read($session_id) { $parameters = array( 'session_id' => $session_id ); $query = "SELECT data FROM sessions WHERE session_id = :session_id AND UTC_TIMESTAMP() < DATE_ADD(modified, INTERVAL lifetime SECOND)"; $db = $this->_db; $db->bisi; $result = $db->execute($parameters, $query); $row = $result->fetch_row(); $row_count = $result->count(); $result->free(); if ($row_count === 1) { return $row['data']; } return null; } public function write($session_id, $data) { $parameters = array( 'session_id' => $session_id, 'data' => $data, 'lifetime' => $this->get_lifetime() ); $query = "INSERT INTO sessions (session_id, data, lifetime) VALUES (:session_id, :data, :lifetime) ON DUPLICATE KEY UPDATE data = :data, lifetime = :lifetime"; $db = $this->_db; $db->bisi; $db->execute($parameters, $query); } public function destroy($session_id = null) { $parameters = array( 'id' => $session_id, ); $query = "DELETE FROM session WHERE session_id = :session_id"; $db = $this->_db; $db->bisi; $db->execute($parameters, $query); } public function close() { return true; } public function clean() { $query = "DELETE FROM sessions WHERE UTC_TIMESTAMP() > DATE_ADD(modified, INTERVAL lifetime SECOND)"; $db = $this->_db; $db->bisi; $db->execute($query); } public function get_lifetime() { return $this->_lifetime; } public function set_lifetime($lifetime, $period = "Days") { switch (strtolower($period)) { default: case 'seconds': break; default: case 'minutes': $lifetime = $lifetime * 60; break; default: case 'hours': $lifetime = $lifetime * 60 * 60; break; default: case 'days': $lifetime = $lifetime * 60 * 60 * 24; break; default: case 'weeks': $lifetime = $lifetime * 60 * 60 * 24 * 7; break; default: case 'months': $lifetime = $lifetime * 60 * 60 * 24 * 30.4368; break; default: case 'years': $lifetime = $lifetime * 60 * 60 * 365.242; break; } $this->_lifetime = $lifetime; return $this; } public function set_db_adapter($db_adapter) { $this->_db = $db_adapter; } } thank you for your help Quote Link to comment Share on other sites More sharing options...
requinix Posted August 15, 2015 Share Posted August 15, 2015 PHP won't just make something null. It looks like the only way to change $_db is using set_db_adapter(). Have you checked whether it's being called with a null $db_adapter? Quote Link to comment Share on other sites More sharing options...
Destramic Posted August 16, 2015 Author Share Posted August 16, 2015 ok i've almost solved the problem...although its all still a bit confusing here is the code i used to call the session_handler which is in my bootstrap public function initialize_session_handler() { echo "here"; $registry = new Registry; $db = $registry->db; $session_handler = new Session_DB_Handler; $session_handler->set_db_adapter($db); $session_handler->set_lifetime(1); session_set_save_handler( array($session_handler, 'open'), array($session_handler, 'close'), array($session_handler, 'read'), array($session_handler, 'write'), array($session_handler, 'destroy'), array($session_handler, 'clean') ); $session = new session; $session->start(); $session->wtf = "now"; echo "here"; } index.php where bootstap is called and initializes my methhods <?php define('DS', DIRECTORY_SEPARATOR); define('PARENT_DIRECTORY_PATH', dirname(dirname(__FILE__))); define('PUBLIC_DIRECTORY', PARENT_DIRECTORY_PATH . DS . 'public' . DS); define('PRIVATE_DIRECTORY', PARENT_DIRECTORY_PATH .DS . 'private' . DS ); use Config\Bootstrap as Bootstrap; require_once PRIVATE_DIRECTORY . 'library' . DS . 'utility' . DS . 'autoloader.class.php'; new Autoloader; $bootstrap = new Bootstrap; $bootstrap->config; $bootstrap->database->connect(); $bootstrap->headers; $bootstrap->timezone; $bootstrap->error_reporting; $bootstrap->error_handler; $bootstrap->session_handler; // session handler is loaded here $bootstrap->geoip; $bootstrap->authentication; //$bootstrap->statistics; $bootstrap->routes; $bootstrap->view_helpers; $bootstrap->framework; // $bootstrap->database->close(); ok well i commented out the closure of the database and now sessions are added to the database as the suppose to do....if i execute the closure of the database then i have no connection on the session handler write (wtf!) only thing i can think of is that the session write happens at the end of php like a destructor? but this is how my html page looks when print_r($db_adpater) hello [html here] hello DB\Driver\MySQLi Object ( [_identifier:protected] => mysqli Object ( [affected_rows] => 2 [client_info] => **************** [client_version] => 50011 [connect_errno] => 0 [connect_error] => [errno] => 0 [error] => [error_list] => Array ( ) [field_count] => 1 [host_info] => Localhost via UNIX socket [info] => [insert_id] => 0 [server_info] => 5.5.5-10.0.20-MariaDB [server_version] => 50505 [stat] => Uptime: 172349 Threads: 1 Questions: 110793 Slow queries: 10 Opens: 1634 Flush tables: 1 Open tables: 400 Queries per second avg: 0.642 [sqlstate] => 00000 [protocol_version] => 10 [thread_id] => 6093 [warning_count] => 0 ) [_config:protected] => Array ( [host] => localhost [username] => *** [password] => *** ) [_table:protected] => [_result:protected] => [_statements:protected] => Array ( ) [_database:protected] => ) surly both echo's of hello and the print_r() executed from the session write should be at the top of my page before the html as it's executed well before the framework...the first echo hello is at the top! honestly this is messed up or i should just give up php now Quote Link to comment Share on other sites More sharing options...
Solution gizmola Posted August 16, 2015 Solution Share Posted August 16, 2015 Did you read this page? http://php.net/manual/en/function.session-set-save-handler.php Session handlers involve a bit of black magic and attempting to trace them can be confusing. With that said, the write handler that is going to write out any changed variables gets executed at the end of script execution. So yes, if you closed the database connection it was going to use, that is not going to work. You should never be issuing html output prior to a session_start(). If you really want debugging/logging then you're much better off adding a file logging feature to your framework, and writing debug information there. Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted August 16, 2015 Share Posted August 16, 2015 i have a more basic question, why are you trying to use database based session data handling? using the default file based session data handling, insuring that you are storing the session data files in a location of your choosing and with permissions set so that only your hosting account can access the files, is adequate in all but a very few cases. you also have a problem with database based session security if you are using the same database connection that your application code is using and ANY of your code allows sql injection, someone can grab all the session data. if the reason you are doing this is for a perceived security problem, to make this as secure as possible, you would need a separate database with a separate connection username that only has access to that database and you would want to encapsulate the database connection into your session handler so that no other code can use possibly it. 1 Quote Link to comment Share on other sites More sharing options...
Destramic Posted August 16, 2015 Author Share Posted August 16, 2015 thank you!...would of helped if i read first =/....what i said is what it was...sorry guys. a good idea about integrating my authentication to my framework though although this session business leaves me a slight problem still....how do i disconnect from the database?...ideally i want the disconnection to be the last script to be executed...only have one connection to my whole site...before i would connect and disconnect per query =/...i've even tried a destruct in my db class but nahh session handler plays up again. what would be my best approach here please? Quote Link to comment Share on other sites More sharing options...
Destramic Posted August 16, 2015 Author Share Posted August 16, 2015 (edited) i have a more basic question, why are you trying to use database based session data handling? using the default file based session data handling, insuring that you are storing the session data files in a location of your choosing and with permissions set so that only your hosting account can access the files, is adequate in all but a very few cases. you also have a problem with database based session security if you are using the same database connection that your application code is using and ANY of your code allows sql injection, someone can grab all the session data. if the reason you are doing this is for a perceived security problem, to make this as secure as possible, you would need a separate database with a separate connection username that only has access to that database and you would want to encapsulate the database connection into your session handler so that no other code can use possibly it. i hope my code protects me from sql injection and csfr...but you have a good point and i don't really have an answer as to why i chosen to use a database instead of the traditional way...just when i read up about it i thought it was a good idea...i'm currently in the middle of building a web server so i can run everything at home...so putting sessions onto a separate database is something i can consider for extra security....or like you said go back to the having sessions in a directory. really appreciate your help guys. although this answers my question about...i'll set a new database up for the sessions and can connect and close in the methods Edited August 16, 2015 by Destramic Quote Link to comment Share on other sites More sharing options...
gizmola Posted August 18, 2015 Share Posted August 18, 2015 Don't concern yourself with closing the database connection, especially when using MySql. When the script is done executing all handles are closed for you. There are very few situations where you need to worry about opening and closing individual database connections within a script. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.