06-04-1394، 01:56 ق.ظ
حتماً برای شما پیش اومده که بنا به دلایل امنیتی یا مواردی مثل امکان کنترل بیشتر روی ورود و خروج کاربران، بخواین مدیریت سشن رو خودتون بدست بگیرین. خوب برای این کار، من یه کلاس نوشتم که به شما اجازه میده سشن رو توی دیتابیس ذخیره کنید. البته این کلاس برای راحتی بیشتر از یه کلاس دیگه استفاده میکنه که وظیفه اون، کار با دیتابیس هست.
کلاس DB :
و این هم کلاس مدیریت سشن در دیتابیس:
برای استفاده از این کلاس، کافیه یه شئ ازش بسازین تا بطور خودکار سشن توی دیتابیس ذخیره بشه و بعد از اون، به شکل عادی با سشنها کار میکنید. مثالی از نحوه استفاده:
اگه سؤالی بود در خدمتم.
کلاس DB :
class DB { /** * @property Resource The connection field */ protected static $con = null; private static $host = 'localhost'; private static $user = 'root'; private static $pass = ''; private static $db = 'test'; public function __construct() { throw new Exception('Cannot create an object from this class.'); } /** * Database connector * Initializes the object and connects to MySQL */ public static function Connect() { self::$con = new mysqli(self::$host, self::$user, self::$pass, self::$db); if (self::$con->connect_errno) { die('Connect failed'); } self::Query('SET NAMES \'utf8\''); self::$con->set_charset('utf8'); } /** * How many rows affected? * @return The number of affected rows by the last excuted query */ public static function AffectedRows() { if(!self::$con) { self::Connect(); } return self::$con->affected_rows; } /** * Executes a select query and return the result as standard PHP array * @param string $query The select query to execute * @return array The result array */ public static function ArrayQuery($query) { if(!self::$con) { self::Connect(); } $result = array(); $rows = self::Query($query); if($rows && ($rows->num_rows > 0)) { while($row = $rows->fetch_assoc()) { $result[] = $row; } } return $result; } /** * Escape a value to use safely in queries * @param string $value The value to escape * @return string|boolean The escaped value if connection exists, false otherwise */ public static function Escape($value) { if(!self::$con) { self::Connect(); } if($value !== null) { return self::Quote(self::$con->real_escape_string($value)); } return 'NULL'; } /** * Execute a query and return the result as a MySQL resource * @param string $query The query to execute * @return resource|boolean The result resource if connection exists, false otherwise */ public static function Query($query) { if(!self::$con) { self::Connect(); } return self::$con->query($query); } /** * Get the last automatic generated id in insert queries */ public static function InsertId() { if(!self::$con) { self::Connect(); } return self::$con->insert_id; } /** * Quote the values * @param string @value The value to quote * @return string The quoted value */ public static function Quote($value) { if($value !== null) { return '\'' . trim($value, '\'') . '\''; } return $value; } }
و این هم کلاس مدیریت سشن در دیتابیس:
class DBSessionHandler { public $sessionTable = 'DBSession'; public $autoCreateSessionTable = true; public $expire = 1200; // 20 minutes public $autoStart = true; /** * Create the session table */ private function _createTable() { DB::Query(" CREATE TABLE `{$this->sessionTable}` ( `id` char(32) COLLATE utf8_bin NOT NULL, `expire` int(11) DEFAULT NULL, `data` longblob, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin "); } /** * Deletes expired session */ private function _deleteExpired() { $expire = time(); DB::Query("DELETE FROM `{$this->sessionTable}` WHERE (`expire`<'{$expire}')"); } /** * Constructor */ public function __construct($autoStart = true) { ini_set('session.save_handler', 'user'); $this->autoStart = $autoStart; if($this->autoStart) { $this->start(); } register_shutdown_function(array($this, 'sessionClose')); } /** * Update the current session ID with a newly generated one. * @param boolean $deleteOldSession Whether to delete the old associated session values or not */ public function regenerateId($deleteOldSession = false) { $oldId = session_id(); if(empty($oldId)) { return; } session_regenerate_id(); $newId = session_id(); if(!$deleteOldSession) { DB::Query("UPDATE `{$this->sessionTable}` SET `id`='{$newId}' WHERE (`id`='{$oldId}')"); } else { $expire = time() + $this->expire; DB::Query("INSERT INTO `{$this->sessionTable}` VALUES ('{$newId}','{$expire}','')"); } } /** * Actually start the session */ public function start() { @session_set_save_handler( array($this, 'sessionOpen'), array($this, 'sessionClose'), array($this, 'sessionRead'), array($this, 'sessionWrite'), array($this, 'sessionDestroy'), array($this, 'sessionGC') ); @session_start(); if(session_id() == '') { throw new Exception('Failed to start session.'); } } /** * Ends the current session and store session data * Do not call this method directly. */ public function sessionClose() { $this->_deleteExpired(); if(session_id() !== '') { @session_write_close(); } } /** * Session destroy handler * Do not call this method directly. * param string $id session ID * @return boolean whether session is destroyed successfully */ public function sessionDestroy($id) { DB::Query("DELETE FROM `{$this->sessionTable}` WHERE (`id`='{$id}')"); return (DB::AffectedRows() > 0); } /** * Session GC (garbage collector) handler * Do not call this method directly. * @param integer $maxLifetime The number of seconds after which data will be seen as 'garbage' and cleaned up. * @return boolean whether session is GCed successfully. */ public function sessionGC($id) { $this->_deleteExpired(); return true; } /** * Session open handler * Do not call this method directly. * @param string @savePath session save path * @param @sessionName session name * @return boolean Whether session is opened successfully */ public function sessionOpen($savePath, $sessionName) { if($this->autoCreateSessionTable) { $this->_deleteExpired(); if(DB::AffectedRows() < 0) { $this->_createTable(); } } return true; } /** * Session read handler * Do not call this method directly. * @param string $id session ID * @return string the session data */ public function sessionRead($id) { $expire = time(); $data = DB::ArrayQuery("SELECT `data` FROM `{$this->sessionTable}` WHERE (`id`='{$id}' AND `expire`>='{$expire}')"); return (count($data) > 0 ? base64_decode($data[0]['data']) : null); } /** * Session write hanlder * Do not call this method directly. * @param string $id Session ID * @param string $data session data * @return boolean Whether session write is successful */ public function sessionWrite($id, $data) { $data = base64_encode($data); $expire = time() + $this->expire; DB::Query("INSERT INTO `{$this->sessionTable}` VALUES ('{$id}','{$data}','{$expire}') ON DUPLICATE KEY UPDATE `data`='{$data}',`expire`='{$expire}'"); } /** * Count online users */ public function onlineCount() { $expire = time(); $data = DB::ArrayQuery("SELECT COUNT(*) AS `total` FROM `{$this->sessionTable}` WHERE (`expire`>='{$expire}')"); return $data[0]['total']; } public function onlineUsers() { $expire = time(); $data = DB::ArrayQuery("SELECT `data` FROM `{$this->sessionTable}` WHERE (`expire`>='{$expire}')"); $users = array(); foreach($data as $item) { $item = base64_decode($item['data']); if(preg_match('#username.*?"(.*?)"#i', $item, $match)) { $users[] = $match[1]; } } return $users; } }
برای استفاده از این کلاس، کافیه یه شئ ازش بسازین تا بطور خودکار سشن توی دیتابیس ذخیره بشه و بعد از اون، به شکل عادی با سشنها کار میکنید. مثالی از نحوه استفاده:
<?php function AutoLoad($class) { require_once 'class.' . $class . '.php'; } spl_autoload_register('AutoLoad'); $dbsh = new DBSessionHandler(); ?> <!doctype html> <html> <head> <title>Database Session Handler</title> <meta charset="utf-8" /> </head> <body> <?php echo '<p>There are ' . $dbsh->onlineCount() . ' user(s) online.</p>' . PHP_EOL; echo 'Online users: <br />' . PHP_EOL; foreach($dbsh->onlineUsers() as $user) { echo $user . '<br />' . PHP_EOL; } ?> </body> </html>
اگه سؤالی بود در خدمتم.