I'm playing with ZF for a while and i have create a plugin that allows you to implement a custom session management system (in this classes you will find sessions stored in database). The benefit of this solution are:
- use PHP native functions like: session_start() and session_destroy();
- use the global $_SESSION
The plugin is using an SQL table (the example is for a MySQL table)
Code: Select all
CREATE TABLE `app_session` (
`session_id` varchar(32) collate latin1_general_ci NOT NULL default '',
`session_time` int(11) NOT NULL default '0',
`session_start` int(11) NOT NULL default '0',
`session_data` text collate latin1_general_ci NOT NULL,
`session_key` varchar(50) collate latin1_general_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;The Session class where factory is located.
Code: Select all
/**
* Application_Plugins_Session_Exception
*/
require_once 'Application/Plugins/Session/Exception.php';
/**
* Factory for Zend_Db_Handler classes.
*
* @param string $adapterName Name of the adapter to return:
* 'database' -> Application_Plugins_Session_Handler_Database
*
* @param array $config An array of adapter configuration keys.
*
* @return Application_Plugins_Session_Handler_Abstract
*
*/
class Application_Plugins_Session {
static public function factory($adapterName, $configuration = null)
{
if (!is_string($adapterName) or !strlen($adapterName)) {
throw new Application_Plugins_Session_Exception('Adapter name must be specified in a string!');
}
$adapterName = 'Application_Plugins_Session_Handler_'.str_replace(' ','_',ucwords(str_replace('_', ' ', $adapterName)));
# Load adapter
Zend::loadClass($adapterName);
return new $adapterName();
}
}Code: Select all
/**
* Abstract class for Zend_Session to help enforce private constructs.
*
* @category Zend
* @package Zend_Session
*/
abstract class Application_Plugins_Session_Handler_Abstract
{
/**
* This is the first function called by PHP when a session is started
*
* @param string $strSessionPath
* @param string $strSessionName
*/
public function open($strSessionPath, $strSessionName)
{
}
/**
* The close function is the last function called by PHP related to the session.
* It does not accept any parameters, and returns either TRUE or FALSE.
*/
public function close()
{
}
/**
* Retrieve any data that is stored for the session, and return it. It is extremely
* important always to return a string from this function, even if it’s empty.
*/
public function read()
{
}
/**
* Write session data
*
* @param string $strSessionId
* @param string $SessionData
*/
public function write($strSessionId,$SessionData)
{
}
/**
* Destroy session, delete all data related to the session id
*
* @param string $strSessionId
*/
public function destroy($strSessionId)
{
}
public function gc($strSessionLifeTime)
{
}
}Code: Select all
/**
* Application_Plugins_Session_Handler_Absstract
*/
require_once 'Application/Plugins/Session/Handler/Abstract.php';
/**
* Application_Plugins_Session_Handler_Exception
*/
require_once 'Application/Plugins/Session/Handler/Exception.php';
class Application_Plugins_Session_Handler_Database extends Application_Plugins_Session_Handler_Abstract
{
public function open($strSessionPath, $strSessionName)
{
return true;
}
public function close()
{
return true;
}
protected function _generateId()
{
do {
# Generate session ID
$strSessionId = md5(uniqid(mt_srand((double) microtime() * 1000000)));
} while ($this->_validateId($strSessionId) === false);
}
protected function _formatSessionData($SessionData)
{
$arrSession = array();
$arrSession = preg_split("/([a-zA-Z0-9\_]+\|)/",$SessionData,-1,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
return array_chunk($arrSession,2);
}
protected function _validateId($strSessionId)
{
# Get database connection
$db = Zend::registry('db');
# Check is the session ID is unique
$select = $db->select();
$select->from('app_session','count(session_id) as session_found');
$select->where('session_id = ?',$strSessionId);
$intValue = $db->fetchOne($select->__toString()) ;
if($intValue) {
return false;
}
else {
return true;
}
}
public function write($strSessionId,$SessionData)
{
# Get database connection
$db = Zend::registry('db');
$arrSessionData = $this->_formatSessionData($SessionData);
# Check if the session id exists
if($this->_validateId($strSessionId))
{
foreach ($arrSessionData as $arrSessionDataKey => $arrSessionDataValue) {
# ID of the session doesn't exist, perform insert
$db->insert("app_session",array("session_id"=>$strSessionId,"session_time"=>time(),"session_start"=>time(),"session_data"=>$arrSessionDataValue[1],"session_key"=>$arrSessionDataValue[0]));
}
}
else
{
# ID of the session exists perform update
foreach ($arrSessionData as $arrSessionDataKey => $arrSessionDataValue) {
# ID of the session doesn't exist, perform insert
$intAffected = $db->update("app_session",array("session_time"=>time(),"session_key"=>$arrSessionDataValue[0],"session_data"=>$arrSessionDataValue[1]),"session_id = '".$strSessionId."' and session_key = '".$arrSessionDataValue[0]."'");
if(!$intAffected) {
$db->insert("app_session",array("session_id"=>$strSessionId,"session_time"=>time(),"session_start"=>time(),"session_data"=>$arrSessionDataValue[1],"session_key"=>$arrSessionDataValue[0]));
}
}
}
return true;
}
public function destroy($strSessionId)
{
# Get database connection
$db = Zend::registry('db');
# Check if the session id exists
if(!$this->_validateId($strSessionId))
{
# Delete session and data associated with it from database
return $db->delete("app_session","session_id= '".$strSessionId."'") > 0 ? true : false;
}
return true;
}
public function gc($strSessionLifeTime = 30)
{
# Get database connection
$db = Zend::registry('db');
# Load application configuration parameters to get session lifetime
$config_app = Zend::registry('config_app');
$strSessionLifeTime = strtotime("-".$config_app->lifetime." minutes");
$db->delete("app_session","session_time < ".$strSessionLifeTime);
return true;
}
public function read($strSessionId)
{
# Get database connection
$db = Zend::registry('db');
# Get all data associated with the session
$select = $db->select();
$select->from('app_session','CONCAT(session_key,session_data) as session_data');
$select->where('session_id = ?',$strSessionId);
$SessionData = $db->fetchAll($select->__toString());
$SessionString = "";
if(is_array($SessionData)) {
foreach ($SessionData as $key => $value) {
$SessionString .= $value['session_data'];
}
}
# If no results the empty string will be returned
return $SessionString;
}
}