From f610527a55f7ef18edc44584263d43e88b766489 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 3 Mar 2013 21:51:06 -0500 Subject: [PATCH] finished session components. --- framework/web/CacheSession.php | 70 ++++++++------- framework/web/Cookie.php | 2 +- framework/web/CookieCollection.php | 8 +- framework/web/DbSession.php | 169 +++++++++++++++---------------------- framework/web/Session.php | 154 ++++++++++++++++----------------- 5 files changed, 191 insertions(+), 212 deletions(-) diff --git a/framework/web/CacheSession.php b/framework/web/CacheSession.php index 9309849..23938f3 100644 --- a/framework/web/CacheSession.php +++ b/framework/web/CacheSession.php @@ -1,6 +1,6 @@ - * @package system.web - * @since 1.0 + * @since 2.0 */ class CacheSession extends Session { /** - * Prefix to the keys for storing cached data - */ - const CACHE_KEY_PREFIX = 'Yii.CacheSession.'; - /** * @var string the ID of the cache application component. Defaults to 'cache' (the primary cache application component.) */ public $cacheID = 'cache'; /** - * @var ICache the cache component + * @var Cache the cache component */ private $_cache; /** - * Initializes the application component. - * This method overrides the parent implementation by checking if cache is available. + * 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; + } + /** + * Returns the cache instance used for storing session data. + * @return Cache the cache instance + * @throws InvalidConfigException if [[cacheID]] does not point to a valid application component. */ - public function init() + public function getCache() { - $this->_cache = Yii::app()->getComponent($this->cacheID); - if (!($this->_cache instanceof ICache)) { - throw new CException(Yii::t('yii', 'CacheSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', - array('{id}' => $this->cacheID))); + if ($this->_cache === null) { + $cache = Yii::$app->getComponent($this->cacheID); + if ($cache instanceof Cache) { + $this->_cache = $cache; + } else { + throw new InvalidConfigException('CacheSession::cacheID must refer to the ID of a cache application component.'); + } } - parent::init(); + return $this->_cache; } /** - * 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. + * Sets the cache instance used by the session component. + * @param Cache $value the cache instance */ - public function getUseCustomStorage() + public function setCache($value) { - return true; + $this->_cache = $value; } /** @@ -74,7 +82,7 @@ class CacheSession extends Session */ public function readSession($id) { - $data = $this->_cache->get($this->calculateKey($id)); + $data = $this->getCache()->get($this->calculateKey($id)); return $data === false ? '' : $data; } @@ -87,7 +95,7 @@ class CacheSession extends Session */ public function writeSession($id, $data) { - return $this->_cache->set($this->calculateKey($id), $data, $this->getTimeout()); + return $this->getCache()->set($this->calculateKey($id), $data, $this->getTimeout()); } /** @@ -98,7 +106,7 @@ class CacheSession extends Session */ public function destroySession($id) { - return $this->_cache->delete($this->calculateKey($id)); + return $this->getCache()->delete($this->calculateKey($id)); } /** @@ -108,6 +116,6 @@ class CacheSession extends Session */ protected function calculateKey($id) { - return self::CACHE_KEY_PREFIX . $id; + return $this->getCache()->buildKey(__CLASS__, $id); } } diff --git a/framework/web/Cookie.php b/framework/web/Cookie.php index 2d8662e..a09285a 100644 --- a/framework/web/Cookie.php +++ b/framework/web/Cookie.php @@ -47,7 +47,7 @@ class Cookie extends \yii\base\Object * By setting this property to true, the cookie will not be accessible by scripting languages, * such as JavaScript, which can effectively help to reduce identity theft through XSS attacks. */ - public $httpOnly = false; + public $httponly = false; /** * Magic method to turn a cookie object into a string without having to explicitly access [[value]]. diff --git a/framework/web/CookieCollection.php b/framework/web/CookieCollection.php index f89a02f..6effa0e 100644 --- a/framework/web/CookieCollection.php +++ b/framework/web/CookieCollection.php @@ -111,7 +111,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ { if (isset($this->_cookies[$cookie->name])) { $c = $this->_cookies[$cookie->name]; - setcookie($c->name, '', 0, $c->path, $c->domain, $c->secure, $c->httpOnly); + setcookie($c->name, '', 0, $c->path, $c->domain, $c->secure, $c->httponly); } $value = $cookie->value; @@ -124,7 +124,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ $value = SecurityHelper::hashData(serialize($value), $key); } - setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); + setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httponly); $this->_cookies[$cookie->name] = $cookie; } @@ -138,7 +138,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ $cookie = $this->_cookies[$cookie]; } if ($cookie instanceof Cookie) { - setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); + setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httponly); unset($this->_cookies[$cookie->name]); } } @@ -149,7 +149,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ public function removeAll() { foreach ($this->_cookies as $cookie) { - setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); + setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httponly); } $this->_cookies = array(); } diff --git a/framework/web/DbSession.php b/framework/web/DbSession.php index feb828a..d565578 100644 --- a/framework/web/DbSession.php +++ b/framework/web/DbSession.php @@ -9,39 +9,42 @@ namespace yii\web; +use Yii; +use yii\db\Connection; +use yii\db\Query; +use yii\base\InvalidConfigException; + /** - * DbSession extends {@link CHttpSession} by using database as session data storage. + * DbSession extends [[Session]] by using database as session data storage. * - * DbSession 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. + * DbSession uses a DB application component to perform DB operations. The ID of the DB application + * component is specified via [[connectionID]] which defaults to 'db'. * - * The following is the table structure: + * By default, DbSession stores session data in a DB table named 'tbl_session'. This table + * must be pre-created. The table name can be changed by setting [[sessionTableName]]. + * The table should have the following structure: * - *
- * CREATE TABLE YiiSession
+ * ~~~
+ * CREATE TABLE tbl_session
  * (
  *     id CHAR(32) PRIMARY KEY,
  *     expire INTEGER,
  *     data BLOB
  * )
- * 
- * Where 'BLOB' refers to the BLOB-type of your preffered database. - * - * DbSession 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. + * where 'BLOB' refers to the BLOB-type of your preferred database. Below are the BLOB type + * that can be used for some popular databases: * - * When using DbSession 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. + * - MySQL: LONGBLOB + * - PostgreSQL: BYTEA + * - MSSQL: BLOB * - * @property boolean $useCustomStorage Whether to use custom storage. + * When using DbSession in a production server, we recommend you create a DB index for the 'expire' + * column in the session table to improve the performance. * * @author Qiang Xue - * @package system.web - * @since 1.0 + * @since 2.0 */ class DbSession extends Session { @@ -60,14 +63,9 @@ class DbSession extends Session * * @see autoCreateSessionTable */ - public $sessionTableName = 'YiiSession'; + public $sessionTableName = 'tbl_session'; /** - * @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 + * @var Connection the DB connection instance */ private $_db; @@ -83,10 +81,9 @@ class DbSession extends Session } /** - * Updates the current session id with a newly generated one. - * Please refer to {@link http://php.net/session_regenerate_id} for more details. + * Updates the current session ID with a newly generated one . + * Please refer to [[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) { @@ -99,93 +96,56 @@ class DbSession extends Session parent::regenerateID(false); $newID = session_id(); - $db = $this->getDbConnection(); + $db = $this->getDb(); - $row = $db->createCommand() - ->select() - ->from($this->sessionTableName) - ->where('id=:id', array(':id' => $oldID)) + $query = new Query; + $row = $query->from($this->sessionTableName) + ->where(array('id' => $oldID)) + ->createCommand($db) ->queryRow(); if ($row !== false) { if ($deleteOldSession) { $db->createCommand()->update($this->sessionTableName, array( 'id' => $newID - ), 'id=:oldID', array(':oldID' => $oldID)); + ), array('id' => $oldID))->execute(); } else { $row['id'] = $newID; - $db->createCommand()->insert($this->sessionTableName, $row); + $db->createCommand()->insert($this->sessionTableName, $row)->execute(); } } else { // shouldn't reach here normally $db->createCommand()->insert($this->sessionTableName, array( 'id' => $newID, 'expire' => time() + $this->getTimeout(), - )); - } - } - - /** - * 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) - { - $driver = $db->getDriverName(); - if ($driver === 'mysql') { - $blob = 'LONGBLOB'; - } elseif ($driver === 'pgsql') { - $blob = 'BYTEA'; - } else { - $blob = 'BLOB'; + ))->execute(); } - $db->createCommand()->createTable($tableName, array( - 'id' => 'CHAR(32) PRIMARY KEY', - 'expire' => 'integer', - 'data' => $blob, - )); } - + /** - * @return CDbConnection the DB connection instance - * @throws CException if {@link connectionID} does not point to a valid application component. + * Returns the DB connection instance used for storing session data. + * @return Connection the DB connection instance + * @throws InvalidConfigException if [[connectionID]] does not point to a valid application component. */ - protected function getDbConnection() + public function getDb() { - if ($this->_db !== null) { - return $this->_db; - } elseif (($id = $this->connectionID) !== null) { - if (($this->_db = Yii::app()->getComponent($id)) instanceof CDbConnection) { - return $this->_db; + if ($this->_db === null) { + $db = Yii::$app->getComponent($this->connectionID); + if ($db instanceof Connection) { + $this->_db = $db; } else { - throw new CException(Yii::t('yii', 'DbSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.', - array('{id}' => $id))); + throw new InvalidConfigException("DbSession::connectionID must refer to the ID of a DB application component."); } - } else { - $dbFile = Yii::app()->getRuntimePath() . DIRECTORY_SEPARATOR . 'session-' . Yii::getVersion() . '.db'; - return $this->_db = new CDbConnection('sqlite:' . $dbFile); } + return $this->_db; } /** - * 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 + * Sets the DB connection used by the session component. + * @param Connection $value the DB connection instance */ - public function openSession($savePath, $sessionName) + public function setDb($value) { - 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; + $this->_db = $value; } /** @@ -196,10 +156,11 @@ class DbSession extends Session */ public function readSession($id) { - $data = $this->getDbConnection()->createCommand() - ->select('data') + $query = new Query; + $data = $query->select(array('data')) ->from($this->sessionTableName) ->where('expire>:expire AND id=:id', array(':expire' => time(), ':id' => $id)) + ->createCommand($this->getDb()) ->queryScalar(); return $data === false ? '' : $data; } @@ -217,20 +178,26 @@ class DbSession extends Session // http://us.php.net/manual/en/function.session-set-save-handler.php try { $expire = time() + $this->getTimeout(); - $db = $this->getDbConnection(); - if ($db->createCommand()->select('id')->from($this->sessionTableName)->where('id=:id', array(':id' => $id))->queryScalar() === false) { + $db = $this->getDb(); + $query = new Query; + $exists = $query->select(array('id')) + ->from($this->sessionTableName) + ->where(array('id' => $id)) + ->createCommand($db) + ->queryScalar(); + if ($exists === false) { $db->createCommand()->insert($this->sessionTableName, array( 'id' => $id, 'data' => $data, 'expire' => $expire, - )); + ))->execute(); } else { $db->createCommand()->update($this->sessionTableName, array( 'data' => $data, 'expire' => $expire - ), 'id=:id', array(':id' => $id)); + ), array('id' => $id))->execute(); } - } catch (Exception $e) { + } catch (\Exception $e) { if (YII_DEBUG) { echo $e->getMessage(); } @@ -248,8 +215,9 @@ class DbSession extends Session */ public function destroySession($id) { - $this->getDbConnection()->createCommand() - ->delete($this->sessionTableName, 'id=:id', array(':id' => $id)); + $this->getDb()->createCommand() + ->delete($this->sessionTableName, array('id' => $id)) + ->execute(); return true; } @@ -261,8 +229,9 @@ class DbSession extends Session */ public function gcSession($maxLifetime) { - $this->getDbConnection()->createCommand() - ->delete($this->sessionTableName, 'expire<:expire', array(':expire' => time())); + $this->getDb()->createCommand() + ->delete($this->sessionTableName, 'expire<:expire', array(':expire' => time())) + ->execute(); return true; } } diff --git a/framework/web/Session.php b/framework/web/Session.php index db03909..0087440 100644 --- a/framework/web/Session.php +++ b/framework/web/Session.php @@ -9,60 +9,47 @@ namespace yii\web; +use Yii; use yii\base\Component; use yii\base\InvalidParamException; /** * Session provides session-level data management and the related configurations. * - * To start the session, call {@link open()}; To complete and send out session data, call {@link close()}; - * To destroy the session, call {@link destroy()}. + * To start the session, call [[open()]]; To complete and send out session data, call [[close()]]; + * To destroy the session, call [[destroy()]]. * - * If {@link autoStart} is set true, the session will be started automatically + * If [[autoStart]] is set true, the session will be started automatically * when the application component is initialized by the application. * * Session can be used like an array to set and get session data. For example, - *
- *   $session=new Session;
- *   $session->open();
- *   $value1=$session['name1'];  // get session variable 'name1'
- *   $value2=$session['name2'];  // get session variable 'name2'
- *   foreach($session as $name=>$value) // traverse all session variables
- *   $session['name3']=$value3;  // set session variable 'name3'
- * 
* - * The following configurations are available for session: - * - * See the corresponding setter and getter documentation for more information. - * Note, these properties must be set before the session is started. + * ~~~ + * $session = new Session; + * $session->open(); + * $value1 = $session['name1']; // get session variable 'name1' + * $value2 = $session['name2']; // get session variable 'name2' + * foreach ($session as $name => $value) // traverse all session variables + * $session['name3'] = $value3; // set session variable 'name3' + * ~~~ * * Session can be extended to support customized session storage. - * Override {@link openSession}, {@link closeSession}, {@link readSession}, - * {@link writeSession}, {@link destroySession} and {@link gcSession} - * and set [[useCustomStorage]] to true. - * Then, the session data will be stored and retrieved using the above methods. + * To do so, override [[useCustomStorage()]] so that it returns true, and + * override these methods with the actual logic about using custom storage: + * [[openSession()]], [[closeSession()]], [[readSession()]], [[writeSession()]], + * [[destroySession()]] and [[gcSession()]]. * * Session is a Web application component that can be accessed via - * {@link CWebApplication::getSession()}. + * `Yii::$app->session`. * - * @property boolean $useCustomStorage Whether to use custom storage. - * @property boolean $isStarted Whether the session has started. - * @property string $sessionID The current session ID. - * @property string $sessionName The current session name. + * @property boolean $useCustomStorage read-only. Whether to use custom storage. + * @property boolean $isActive Whether the session has started. + * @property string $id The current session ID. + * @property string $name The current session name. * @property string $savePath The current session save path, defaults to '/tmp'. * @property array $cookieParams The session cookie parameters. * @property string $cookieMode How to use cookie to store session ID. Defaults to 'Allow'. - * @property float $gCProbability The probability (percentage) that the gc (garbage collection) process is started on every session initialization, defaults to 1 meaning 1% chance. + * @property float $gcProbability The probability (percentage) that the gc (garbage collection) process is started on every session initialization. * @property boolean $useTransparentSessionID Whether transparent sid support is enabled or not, defaults to false. * @property integer $timeout The number of seconds after which data will be seen as 'garbage' and cleaned up, defaults to 1440 seconds. * @property SessionIterator $iterator An iterator for traversing the session variables. @@ -94,11 +81,9 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Returns a value indicating whether to use custom session storage. - * To use custom session storage, override this method and return This method should be overridden to return true if custom session storage handler should be used. - * If returning true, make sure the methods {@link openSession}, {@link closeSession}, {@link readSession}, - * {@link writeSession}, {@link destroySession}, and {@link gcSession} are overridden in child - * class, because they will be used as the callback handlers. - * The default implementation always return false. + * This method should be overridden to return true by child classes that implement custom session storage. + * To implement custom session storage, override these methods: [[openSession()]], [[closeSession()]], + * [[readSession()]], [[writeSession()]], [[destroySession()]] and [[gcSession()]]. * @return boolean whether to use custom storage. */ public function getUseCustomStorage() @@ -107,24 +92,34 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co } /** - * Starts the session if it has not started yet. + * Starts the session. */ public function open() { + // this is available in PHP 5.4.0+ + if (function_exists('session_status')) { + if (session_status() == PHP_SESSION_ACTIVE) { + return; + } + } + if ($this->getUseCustomStorage()) { - @session_set_save_handler(array($this, 'openSession'), array($this, 'closeSession'), array($this, 'readSession'), array($this, 'writeSession'), array($this, 'destroySession'), array($this, 'gcSession')); + @session_set_save_handler( + array($this, 'openSession'), + array($this, 'closeSession'), + array($this, 'readSession'), + array($this, 'writeSession'), + array($this, 'destroySession'), + array($this, 'gcSession') + ); } @session_start(); - if (YII_DEBUG && session_id() == '') { - $message = Yii::t('yii', 'Failed to start session.'); - if (function_exists('error_get_last')) { - $error = error_get_last(); - if (isset($error['message'])) { - $message = $error['message']; - } - } - Yii::log($message, CLogger::LEVEL_WARNING, 'system.web.Session'); + + if (session_id() == '') { + $error = error_get_last(); + $message = isset($error['message']) ? $error['message'] : 'Failed to start session.'; + Yii::warning($message, __CLASS__); } } @@ -152,15 +147,21 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * @return boolean whether the session has started */ - public function getIsStarted() + public function getIsActive() { - return session_id() !== ''; + if (function_exists('session_status')) { + // available in PHP 5.4.0+ + return session_status() == PHP_SESSION_ACTIVE; + } else { + // this is not very reliable + return session_id() !== ''; + } } /** * @return string the current session ID */ - public function getSessionID() + public function getId() { return session_id(); } @@ -168,16 +169,15 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * @param string $value the session ID for the current session */ - public function setSessionID($value) + public function setId($value) { session_id($value); } /** - * Updates the current session id with a newly generated one . - * Please refer to {@link http://php.net/session_regenerate_id} for more details. + * Updates the current session ID with a newly generated one . + * Please refer to [[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) { @@ -187,15 +187,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * @return string the current session name */ - public function getSessionName() + public function getName() { return session_name(); } /** - * @param string $value the session name for the current session, must be an alphanumeric string, defaults to PHPSESSID + * @param string $value the session name for the current session, must be an alphanumeric string. + * It defaults to "PHPSESSID". */ - public function setSessionName($value) + public function setName($value) { session_name($value); } @@ -209,16 +210,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co } /** - * @param string $value the current session save path - * @throws CException if the path is not a valid directory + * @param string $value the current session save path. This can be either a directory name or a path alias. + * @throws InvalidParamException if the path is not a valid directory */ public function setSavePath($value) { - if (is_dir($value)) { - session_save_path($value); + $path = Yii::getAlias($value); + if ($path !== false && is_dir($path)) { + session_save_path($path); } else { - throw new CException(Yii::t('yii', 'Session.savePath "{path}" is not a valid directory.', - array('{path}' => $value))); + throw new InvalidParamException("Session save path is not a valid directory: $value"); } } @@ -235,7 +236,8 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co * Sets the session cookie parameters. * The effect of this method only lasts for the duration of the script. * Call this method before the session starts. - * @param array $value cookie parameters, valid keys include: lifetime, path, domain, secure. + * @param array $value cookie parameters, valid keys include: lifetime, path, domain, secure and httponly. + * @throws InvalidParamException if the parameters are incomplete. * @see http://us2.php.net/manual/en/function.session-set-cookie-params.php */ public function setCookieParams($value) @@ -243,10 +245,10 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co $data = session_get_cookie_params(); extract($data); extract($value); - if (isset($httponly)) { + if (isset($lifetime, $path, $domain, $secure, $httponly)) { session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly); } else { - session_set_cookie_params($lifetime, $path, $domain, $secure); + throw new InvalidParamException('Please make sure these parameters are provided: lifetime, path, domain, secure and httponly.'); } } @@ -348,7 +350,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Session open handler. - * This method should be overridden if [[useCustomStorage]] is set true. + * This method should be overridden if [[useCustomStorage()]] returns true. * Do not call this method directly. * @param string $savePath session save path * @param string $sessionName session name @@ -361,7 +363,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Session close handler. - * This method should be overridden if [[useCustomStorage]] is set true. + * This method should be overridden if [[useCustomStorage()]] returns true. * Do not call this method directly. * @return boolean whether session is closed successfully */ @@ -372,7 +374,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Session read handler. - * This method should be overridden if [[useCustomStorage]] is set true. + * This method should be overridden if [[useCustomStorage()]] returns true. * Do not call this method directly. * @param string $id session ID * @return string the session data @@ -384,7 +386,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Session write handler. - * This method should be overridden if [[useCustomStorage]] is set true. + * This method should be overridden if [[useCustomStorage()]] returns true. * Do not call this method directly. * @param string $id session ID * @param string $data session data @@ -397,7 +399,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Session destroy handler. - * This method should be overridden if [[useCustomStorage]] is set true. + * This method should be overridden if [[useCustomStorage()]] returns true. * Do not call this method directly. * @param string $id session ID * @return boolean whether session is destroyed successfully @@ -409,7 +411,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co /** * Session GC (garbage collection) handler. - * This method should be overridden if [[useCustomStorage]] is set true. + * This method should be overridden if [[useCustomStorage()]] returns true. * 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