123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <?php
- /**
- * CDbHttpSession class
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.yiiframework.com/
- * @copyright 2008-2013 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- /**
- * CDbHttpSession extends {@link CHttpSession} by using database as session data storage.
- *
- * CDbHttpSession stores session data in a DB table named 'YiiSession'. The table name
- * can be changed by setting {@link sessionTableName}. If the table does not exist,
- * it will be automatically created if {@link autoCreateSessionTable} is set true.
- *
- * The following is the table structure:
- *
- * <pre>
- * CREATE TABLE YiiSession
- * (
- * id CHAR(32) PRIMARY KEY,
- * expire INTEGER,
- * data BLOB
- * )
- * </pre>
- * Where 'BLOB' refers to the BLOB-type of your preffered database.
- *
- * Note that if your session IDs are more than 32 characters (can be changed via
- * session.hash_bits_per_character or session.hash_function) you should modify
- * SQL schema accordingly.
- *
- * CDbHttpSession relies on {@link http://www.php.net/manual/en/ref.pdo.php PDO} to access database.
- *
- * By default, it will use an SQLite3 database named 'session-YiiVersion.db' under the application runtime directory.
- * You can also specify {@link connectionID} so that it makes use of a DB application component to access database.
- *
- * When using CDbHttpSession in a production server, we recommend you pre-create the session DB table
- * and set {@link autoCreateSessionTable} to be false. This will greatly improve the performance.
- * You may also create a DB index for the 'expire' column in the session table to further improve the performance.
- *
- * @property boolean $useCustomStorage Whether to use custom storage.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @package system.web
- * @since 1.0
- */
- class CDbHttpSession extends CHttpSession
- {
- /**
- * @var string the ID of a {@link CDbConnection} application component. If not set, a SQLite database
- * will be automatically created and used. The SQLite database file is
- * is <code>protected/runtime/session-YiiVersion.db</code>.
- */
- public $connectionID;
- /**
- * @var string the name of the DB table to store session content.
- * Note, if {@link autoCreateSessionTable} is false and you want to create the DB table manually by yourself,
- * you need to make sure the DB table is of the following structure:
- * <pre>
- * (id CHAR(32) PRIMARY KEY, expire INTEGER, data BLOB)
- * </pre>
- * @see autoCreateSessionTable
- */
- public $sessionTableName='YiiSession';
- /**
- * @var boolean whether the session DB table should be automatically created if not exists. Defaults to true.
- * @see sessionTableName
- */
- public $autoCreateSessionTable=true;
- /**
- * @var CDbConnection the DB connection instance
- */
- private $_db;
- /**
- * Returns a value indicating whether to use custom session storage.
- * This method overrides the parent implementation and always returns true.
- * @return boolean whether to use custom storage.
- */
- public function getUseCustomStorage()
- {
- return true;
- }
- /**
- * Updates the current session id with a newly generated one.
- * Please refer to {@link http://php.net/session_regenerate_id} for more details.
- * @param boolean $deleteOldSession Whether to delete the old associated session file or not.
- * @since 1.1.8
- */
- public function regenerateID($deleteOldSession=false)
- {
- $oldID=session_id();
- // if no session is started, there is nothing to regenerate
- if(empty($oldID))
- return;
- parent::regenerateID(false);
- $newID=session_id();
- $db=$this->getDbConnection();
- $row=$db->createCommand()
- ->select()
- ->from($this->sessionTableName)
- ->where('id=:id',array(':id'=>$oldID))
- ->queryRow();
- if($row!==false)
- {
- if($deleteOldSession)
- $db->createCommand()->update($this->sessionTableName,array(
- 'id'=>$newID
- ),'id=:oldID',array(':oldID'=>$oldID));
- else
- {
- $row['id']=$newID;
- $db->createCommand()->insert($this->sessionTableName, $row);
- }
- }
- else
- {
- // shouldn't reach here normally
- $db->createCommand()->insert($this->sessionTableName, array(
- 'id'=>$newID,
- 'expire'=>time()+$this->getTimeout(),
- 'data'=>'',
- ));
- }
- }
- /**
- * Creates the session DB table.
- * @param CDbConnection $db the database connection
- * @param string $tableName the name of the table to be created
- */
- protected function createSessionTable($db,$tableName)
- {
- switch($db->getDriverName())
- {
- case 'mysql':
- $blob='LONGBLOB';
- break;
- case 'pgsql':
- $blob='BYTEA';
- break;
- case 'sqlsrv':
- case 'mssql':
- case 'dblib':
- $blob='VARBINARY(MAX)';
- break;
- default:
- $blob='BLOB';
- break;
- }
- $db->createCommand()->createTable($tableName,array(
- 'id'=>'CHAR(32) PRIMARY KEY',
- "coach_id" => "bigint",
- "update_time" => "bigint",
- 'expire'=>'integer',
- 'data'=>$blob,
- ));
- }
- /**
- * @return CDbConnection the DB connection instance
- * @throws CException if {@link connectionID} does not point to a valid application component.
- */
- protected function getDbConnection()
- {
- if($this->_db!==null)
- return $this->_db;
- elseif(($id=$this->connectionID)!==null)
- {
- if(($this->_db=Yii::app()->getComponent($id)) instanceof CDbConnection)
- return $this->_db;
- else
- throw new CException(Yii::t('yii','CDbHttpSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.',
- array('{id}'=>$id)));
- }
- else
- {
- $dbFile=Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR.'session-'.Yii::getVersion().'.db';
- return $this->_db=new CDbConnection('sqlite:'.$dbFile);
- }
- }
- /**
- * Session open handler.
- * Do not call this method directly.
- * @param string $savePath session save path
- * @param string $sessionName session name
- * @return boolean whether session is opened successfully
- */
- public function openSession($savePath,$sessionName)
- {
- if($this->autoCreateSessionTable)
- {
- $db=$this->getDbConnection();
- $db->setActive(true);
- try
- {
- $db->createCommand()->delete($this->sessionTableName,'expire<:expire',array(':expire'=>time()));
- }
- catch(Exception $e)
- {
- $this->createSessionTable($db,$this->sessionTableName);
- }
- }
- return true;
- }
- /**
- * Session read handler.
- * Do not call this method directly.
- * @param string $id session ID
- * @return string the session data
- */
- public function readSession($id)
- {
- $expire=time()+$this->getTimeout();
- $db=$this->getDbConnection();
- if($db->getDriverName()=='sqlsrv' || $db->getDriverName()=='mssql' || $db->getDriverName()=='dblib')
- $select='CONVERT(VARCHAR(MAX), data)';
- else
- $select='data';
-
- $db->createCommand()->update($this->sessionTableName,array(
- "update_time" => time(),
- 'expire'=>$expire,
- ),'id=:id',array(':id'=>$id));
-
- $data=$db->createCommand()
- ->select($select)
- ->from($this->sessionTableName)
- ->where('expire>:expire AND id=:id',array(':expire'=>time(),':id'=>$id))
- ->queryScalar();
- return $data===false?'':$data;
- }
- /**
- * Session write handler.
- * 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 writeSession($id,$data)
- {
- // exception must be caught in session write handler
- // http://us.php.net/manual/en/function.session-set-save-handler.php
- try
- {
- $expire=time()+$this->getTimeout();
- $db=$this->getDbConnection();
- $coachId = isset($_SESSION["coachInfo"]["coach_id"]) ? $_SESSION["coachInfo"]["coach_id"] : null;
- if($db->getDriverName()=='sqlsrv' || $db->getDriverName()=='mssql' || $db->getDriverName()=='dblib')
- $data=new CDbExpression('CONVERT(VARBINARY(MAX), '.$db->quoteValue($data).')');
- if($db->createCommand()->select('id')->from($this->sessionTableName)->where('id=:id',array(':id'=>$id))->queryScalar()===false)
- $db->createCommand()->insert($this->sessionTableName,array(
- 'id'=>$id,
- "coach_id" => $coachId,
- "update_time" => time(),
- 'data'=>$data,
- 'expire'=>$expire,
- ));
- else
- $db->createCommand()->update($this->sessionTableName,array(
- "coach_id" => $coachId,
- "update_time" => time(),
- 'data'=>$data,
- 'expire'=>$expire
- ),'id=:id',array(':id'=>$id));
- }
- catch(Exception $e)
- {
- if(YII_DEBUG)
- echo $e->getMessage();
- // it is too late to log an error message here
- return false;
- }
- return true;
- }
- /**
- * Session destroy handler.
- * Do not call this method directly.
- * @param string $id session ID
- * @return boolean whether session is destroyed successfully
- */
- public function destroySession($id)
- {
- $this->getDbConnection()->createCommand()
- ->delete($this->sessionTableName,'id=:id',array(':id'=>$id));
- return true;
- }
- /**
- * Session GC (garbage collection) 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 gcSession($maxLifetime)
- {
- $time = time() - $this->getTimeout();
- $this->getDbConnection()->createCommand()
- ->delete($this->sessionTableName,'update_time<=:time',array(':time'=>$time));
- return true;
- }
- }
|