ZF2 Dafault Database Session Storage

I am busy writing a database session module, so I can quickly install it between multiple applications. The module will be loaded from the autoloader as the first module to start. What I'm trying to do is change the default container / session handler, which will be the default session handler for all modules, and should also be hosted sessions in the database. I've been handling zf2 sessions for a long time, and log errors make sense. So here is what I still have. The main module with Module.php containing ...

DBSession namespace

use Zend\Mvc\ModuleRouteListener; class Module { public function onBootstrap($e) { $e->getApplication()->getServiceManager()->get('translator'); $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); $config = $e->getApplication()->getServiceManager()->get('Config'); $controller = $e->getTarget(); $controller->config = $config; new \DBSession\Storage\DBStorage(); } public function getConfig() { return include __DIR__ . '/config/module.config.php'; } public function getAutoloaderConfig() { return array( 'Zend\Loader\ClassMapAutoloader' => array( __DIR__ . '/autoload_classmap.php', ), 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), ), ); } } 

And the actual class that initiates the DB session handler.

 namespace DBSession\Storage; use Zend\Session\SaveHandler\DbTableGateway; use Zend\Session\SaveHandler\DbTableGatewayOptions; use Zend\Db\Adapter\Adapter; use Zend\Session\SessionManager; use Zend\Session\Container; class DBStorage { public function __construct() { $dbAdapter = new Adapter(array( 'driver' => 'Mysqli', 'host' => 'localhost', 'dbname' => 'zf2_session', 'username' => 'zf2', 'password' => 'testme', 'options' => array( 'buffer_results' => true, ), )); $tableGateway = new \Zend\Db\TableGateway\TableGateway('session', $dbAdapter); $gwOpts = new DbTableGatewayOptions(); $gwOpts->setDataColumn('data'); $gwOpts->setIdColumn('id'); $gwOpts->setLifetimeColumn('lifetime'); $gwOpts->setModifiedColumn('modified'); $gwOpts->setNameColumn('name'); $saveHandler = new DbTableGateway($tableGateway, $gwOpts); $sessionManager = new SessionManager(); $sessionManager->setSaveHandler($saveHandler); return Container::setDefaultManager($sessionManager); } } 

When I try to create a session, I see the following in the logs that I have, how to fix it. It starts to make me hate magic ...

 [29-Nov-2012 20:47:28 UTC] PHP Fatal error: Uncaught exception 'Zend\Db\Sql\Exception\InvalidArgumentException' with message 'Not a valid magic property for this object' in /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php:764 Stack trace: #0 /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php(163): Zend\Db\Sql\Select->__get('tableReadOnly') #1 /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php(146): Zend\Db\Sql\Select->from('session') #2 /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Sql.php(65): Zend\Db\Sql\Select->__construct('session') #3 /document_root/vendor/zendframework/zendframework/library/Zend/Db/TableGateway/AbstractTableGateway.php(191): Zend\Db\Sql\Sql->select() #4 /document_root/vendor/zendframework/zendframework/library/Zend/Session/SaveHandler/DbTableGateway.php(134): Zend\Db\TableGateway\AbstractTableGateway->select(Array) #5 [internal function]: Zend\Session\SaveHandler\DbTableGateway->write(' in /document_root/vendor/zendframework/zendframework/library/Zend/Db/Sql/Select.php on line 764 
+4
source share
3 answers

After all the fixes recently introduced in ZF2, my original solution now works without changes, however I added a new module for those who want to use it, and this reduces the need to do it all manually.

Installation information is in the readme file: https://github.com/Nitecon/DBSessionStorage

Enjoy and let me know if you have any problems.

+4
source

update:

zend framework> = 2.2, this question no longer exists.

Old answer:

I faced the same problem while saving the session in the database, I wrote the initDbSession function inside the base class of the module \module\Application\Module.php

 class Module { public function onBootstrap(MvcEvent $e) { $e->getApplication()->getServiceManager()->get('translator'); $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); // session start from here $this->initDbSession( $e ); } /** * Store session into database * * @param type $e */ private function initDbSession( MvcEvent $e ) { // grab the config array $serviceManager = $e->getApplication()->getServiceManager(); $config = $serviceManager->get('config'); $dbAdapter = $serviceManager->get('Zend\Db\Adapter\Adapter'); /* some how this not works for me $sessionOptions = new \Zend\Session\SaveHandler\DbTableGatewayOptions( null ); $sessionTableGateway = new \Zend\Db\TableGateway\TableGateway('session', $dbAdapter); $saveHandler = new \Zend\Session\SaveHandler\DbTableGateway($sessionTableGateway, $sessionOptions); */ /* I written my own save handler , I am using mysql as database */ $saveHandler = new \My\Session\SaveHandler\Mysql( $config['db'] ); $sessionConfig = new \Zend\Session\Config\SessionConfig(); $sessionConfig->setOptions($config['session']); // pass the saveHandler to the sessionManager and start the session $sessionManager = new \Zend\Session\SessionManager( $sessionConfig , NULL, $saveHandler ); $sessionManager->start(); \Zend\Session\Container::setDefaultManager($sessionManager); } // other function goes here ... 

Here is my configuration file, which is located in \config\autoload\global.php

 return array( 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=zf2;host=localhost', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'', 'buffer_results' => true ), 'username' => 'root', 'password' => '', 'host' => 'localhost', 'dbname' => 'zf2', ), 'session' => array( 'remember_me_seconds' => 2419200, 'use_cookies' => true, 'cookie_httponly' => true, 'cookie_lifetime' => 2419200, 'gc_maxlifetime' => 2419200, ), 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory' ) ) ); 

Mysql table structure

 CREATE TABLE `session` ( `id` CHAR(32) NOT NULL DEFAULT '', `name` VARCHAR(255) NOT NULL, `modified` INT(11) NULL DEFAULT NULL, `lifetime` INT(11) NULL DEFAULT NULL, `data` TEXT NULL, PRIMARY KEY (`id`) )COLLATE='utf8_general_ci' ENGINE=InnoDB; 

The custom Mysql save handler class is shown below. I wrote this class because the new Zend\Session\SaveHandler\DbTableGateway not working on my server. My custom Mysql session session handler class written in \library\My\Session\SaveHandler\Mysql.php

 <?php namespace My\Session\SaveHandler; use Zend\Session\SaveHandler\SaveHandlerInterface; /** * Description of Mysql * * @author rab */ class Mysql implements SaveHandlerInterface { /** * Session Save Path * * @var string */ protected $sessionSavePath; /** * Session Name * * @var string */ protected $sessionName; /** * Lifetime * @var int */ protected $lifetime; /** * Constructor * */ public function __construct( $dbConfig ) { $this->dbconn = mysql_connect( $dbConfig['host'], $dbConfig['username'], $dbConfig['password'] ); if ( $this->dbconn ) { return mysql_select_db($dbConfig['dbname'], $this->dbconn); } } /** * Open the session * * @return bool */ public function open( $savePath, $name ) { $this->sessionSavePath = $savePath; $this->sessionName = $name; $this->lifetime = ini_get('session.gc_maxlifetime'); return true; } /** * Close the session * * @return bool */ public function close() { return mysql_close($this->dbconn); } /** * Read the session * * @param int session id * @return string string of the sessoin */ public function read($id) { $id = mysql_real_escape_string($id); $sql = "SELECT `data` FROM `session` " . "WHERE id = '$id'"; if ( $result = mysql_query($sql, $this->dbconn)) { if ( mysql_num_rows($result) ) { $record = mysql_fetch_assoc($result); return $record['data']; } } return ''; } /** * Write the session * * @param int session id * @param string data of the session */ public function write($id, $data ) { $data = (string) $data ; $dbdata = array( 'modified' => time(), 'data' => mysql_real_escape_string( $data ) , ); $selectSql = "SELECT * FROM session WHERE id = '$id' AND name = '{$this->sessionName}' "; $rs = mysql_query( $selectSql, $this->dbconn ); if ( $rs = mysql_query( $selectSql , $this->dbconn)) { if ( mysql_num_rows($rs) ) { $updateSql = "UPDATE `session` SET `modified`= '".$dbdata['modified'] . "' , `data`= '".$dbdata['data']. "' WHERE id= '$id' AND name = '{$this->sessionName}' "; mysql_query( $updateSql , $this->dbconn ); return true; } } $dbdata['lifetime'] = $this->lifetime; $dbdata['id'] = $id; $dbdata['name'] = $this->sessionName; $insertSql = "INSERT INTO session (". implode(',' , array_keys($dbdata)) .")" ."VALUES ('" . implode("','" , array_values( $dbdata )). "')"; return mysql_query( $insertSql, $this->dbconn); } /** * Destoroy the session * * @param int session id * @return bool */ public function destroy($id) { $sql = sprintf("DELETE FROM `session` WHERE `id` = '%s'", $id); return mysql_query($sql, $this->dbconn); } /** * Garbage Collector * * @param int life time (sec.) * @return bool */ public function gc( $maxlifetime ) { $sql = sprintf("DELETE FROM `session` WHERE `modified` < '%s'", mysql_real_escape_string(time() - $maxlifetime) ); return mysql_query($sql, $this->dbconn); } } 

Which saves the session values ​​in the db table. For more information, you can check http://php.net/manual/en/function.session-set-save-handler.php

+5
source

Here's another similar solution: How to use cookies in Zend Framework 2?

make sure you change this line:

 Session::setDefaultManager($sessionManager); 

With the help of this:

 Container::setDefaultManager($sessionManager); 

Using:

 use Zend\Session\Container; 
0
source

All Articles