Browse Source

added redis Session

as suggested in issue #1316
tags/2.0.0-beta
Carsten Brandt 11 years ago
parent
commit
3cb366020a
  1. 2
      extensions/redis/Cache.php
  2. 119
      extensions/redis/README.md
  3. 157
      extensions/redis/Session.php
  4. 4
      extensions/redis/composer.json
  5. 2
      framework/yii/caching/Cache.php

2
extensions/redis/Cache.php

@ -40,7 +40,7 @@ use yii\base\InvalidConfigException;
* ] * ]
* ~~~ * ~~~
* *
* Or if you have configured the redis connection as an application component, the following is sufficient: * Or if you have configured the redis [[Connection]] as an application component, the following is sufficient:
* *
* ~~~ * ~~~
* [ * [

119
extensions/redis/README.md

@ -1,9 +1,9 @@
Redis Cache and ActiveRecord for Yii 2 Redis Cache, Session and ActiveRecord for Yii 2
====================================== ===============================================
This extension provides the [redis](http://redis.io/) key-value store support for the Yii2 framework. This extension provides the [redis](http://redis.io/) key-value store support for the Yii2 framework.
It includes a `Cache` class and implents the `ActiveRecord` pattern that allows you to store active It includes a `Cache` and `Session` storage handler and implents the `ActiveRecord` pattern that allows
records in redis. you to store active records in redis.
To use this extension, you have to configure the Connection class in your application configuration: To use this extension, you have to configure the Connection class in your application configuration:
@ -21,7 +21,31 @@ return [
]; ];
``` ```
To use the `Cache` component, you also have to configure the `cache` component to be `yii\redis\Cache`: Installation
------------
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```
php composer.phar require yiisoft/yii2-redis "*"
```
or add
```json
"yiisoft/yii2-redis": "*"
```
to the require section of your composer.json.
Using the Cache component
-------------------------
To use the `Cache` component, in addtition to configuring the connection as described above,
you also have to configure the `cache` component to be `yii\redis\Cache`:
```php ```php
return [ return [
@ -36,7 +60,7 @@ return [
``` ```
If you only use the redis cache, you can also configure the parameters of the connection within the If you only use the redis cache, you can also configure the parameters of the connection within the
cache component: cache component (no connection application component needs to be configured in this case):
```php ```php
return [ return [
@ -55,26 +79,44 @@ return [
]; ];
``` ```
Using the Session component
---------------------------
Installation To use the `Session` component, in addtition to configuring the connection as described above,
------------ you also have to configure the `session` component to be `yii\redis\Session`:
The preferred way to install this extension is through [composer](http://getcomposer.org/download/). ```php
return [
Either run //....
'components' => [
``` // ...
php composer.phar require yiisoft/yii2-redis "*" 'session' => [
'class' => 'yii\redis\Session',
],
]
];
``` ```
or add If you only use the redis session, you can also configure the parameters of the connection within the
cache component (no connection application component needs to be configured in this case):
```json ```php
"yiisoft/yii2-redis": "*" return [
//....
'components' => [
// ...
'session' => [
'class' => 'yii\redis\Session',
'redis' => [
'hostname' => 'localhost',
'port' => 6379,
'database' => 0,
],
],
]
];
``` ```
to the require section of your composer.json.
Using the redis ActiveRecord Using the redis ActiveRecord
---------------------------- ----------------------------
@ -92,10 +134,29 @@ The following is an example model called `Customer`:
```php ```php
class Customer extends \yii\redis\ActiveRecord class Customer extends \yii\redis\ActiveRecord
{ {
public function attributes() /**
{ * @return array the list of attributes for this record
return ['id', 'name', 'address', 'registration_date']; */
} public function attributes()
{
return ['id', 'name', 'address', 'registration_date'];
}
/**
* @return ActiveRelation defines a relation to the Order record (can be in other database, e.g. elasticsearch or sql)
*/
public function getOrders()
{
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
/**
* Defines a scope that modifies the `$query` to return only active(status = 1) customers
*/
public static function active($query)
{
$query->andWhere(array('status' => 1));
}
} }
``` ```
@ -109,3 +170,15 @@ It supports the same interface and features except the following limitations:
- `via`-relations can not be defined via a table as there are not tables in redis. You can only define relations via other records. - `via`-relations can not be defined via a table as there are not tables in redis. You can only define relations via other records.
It is also possible to define relations from redis ActiveRecords to normal ActiveRecord classes and vice versa. It is also possible to define relations from redis ActiveRecords to normal ActiveRecord classes and vice versa.
Usage example:
```php
$customer = new Customer();
$customer->attributes = ['name' => 'test'];
$customer->save();
echo $customer->id; // id will automatically be incremented if not set explicitly
$customer = Customer::find()->where(['name' => 'test'])->one(); // find by query
$customer = Customer::find()->active()->all(); // find all by query (using the `active` scope)
```

157
extensions/redis/Session.php

@ -0,0 +1,157 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\redis;
use Yii;
use yii\base\InvalidConfigException;
/**
* Redis Session implements a session component using [redis](http://redis.io/) as the storage medium.
*
* Redis Session requires redis version 2.6.12 or higher to work properly.
*
* It needs to be configured with a redis [[Connection]] that is also configured as an application component.
* By default it will use the `redis` application component.
*
* To use redis Session as the session application component, configure the application as follows,
*
* ~~~
* [
* 'components' => [
* 'session' => [
* 'class' => 'yii\redis\Session',
* 'redis' => [
* 'hostname' => 'localhost',
* 'port' => 6379,
* 'database' => 0,
* ]
* ],
* ],
* ]
* ~~~
*
* Or if you have configured the redis [[Connection]] as an application component, the following is sufficient:
*
* ~~~
* [
* 'components' => [
* 'session' => [
* 'class' => 'yii\redis\Session',
* // 'redis' => 'redis' // id of the connection application component
* ],
* ],
* ]
* ~~~
*
* @property boolean $useCustomStorage Whether to use custom storage. This property is read-only.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class Session extends \yii\web\Session
{
/**
* @var Connection|string|array the Redis [[Connection]] object or the application component ID of the Redis [[Connection]].
* This can also be an array that is used to create a redis [[Connection]] instance in case you do not want do configure
* redis connection as an application component.
* After the Session object is created, if you want to change this property, you should only assign it
* with a Redis [[Connection]] object.
*/
public $redis = 'redis';
/**
* @var string a string prefixed to every cache key so that it is unique. If not set,
* it will use a prefix generated from [[Application::id]]. You may set this property to be an empty string
* if you don't want to use key prefix. It is recommended that you explicitly set this property to some
* static value if the cached data needs to be shared among multiple applications.
*
* To ensure interoperability, only alphanumeric characters should be used.
*/
public $keyPrefix;
/**
* Initializes the redis Session component.
* This method will initialize the [[redis]] property to make sure it refers to a valid redis connection.
* @throws InvalidConfigException if [[redis]] is invalid.
*/
public function init()
{
parent::init();
if (is_string($this->redis)) {
$this->redis = Yii::$app->getComponent($this->redis);
} else if (is_array($this->redis)) {
if (!isset($this->redis['class'])) {
$this->redis['class'] = Connection::className();
}
$this->redis = Yii::createObject($this->redis);
}
if (!$this->redis instanceof Connection) {
throw new InvalidConfigException("Session::redis must be either a Redis connection instance or the application component ID of a Redis connection.");
}
if ($this->keyPrefix === null) {
$this->keyPrefix = substr(md5(Yii::$app->id), 0, 5);
} elseif (!ctype_alnum($this->keyPrefix)) {
throw new InvalidConfigException(get_class($this) . '::keyPrefix should only contain alphanumeric characters.');
}
}
/**
* 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;
}
/**
* Session read handler.
* Do not call this method directly.
* @param string $id session ID
* @return string the session data
*/
public function readSession($id)
{
$data = $this->redis->executeCommand('GET', [$this->calculateKey($id)]);
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)
{
return (bool) $this->redis->executeCommand('SET', [$this->calculateKey($id), $data, 'EX', $this->getTimeout()]);
}
/**
* 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)
{
return (bool) $this->redis->executeCommand('DEL', [$this->calculateKey($id)]);
}
/**
* Generates a unique key used for storing session data in cache.
* @param string $id session variable name
* @return string a safe cache key associated with the session variable name
*/
protected function calculateKey($id)
{
return $this->keyPrefix . md5(json_encode([__CLASS__, $id]));
}
}

4
extensions/redis/composer.json

@ -1,7 +1,7 @@
{ {
"name": "yiisoft/yii2-redis", "name": "yiisoft/yii2-redis",
"description": "Redis Cache and ActiveRecord for the Yii framework", "description": "Redis Cache, Session and ActiveRecord for the Yii framework",
"keywords": ["yii", "redis", "active-record", "cache"], "keywords": ["yii", "redis", "active-record", "cache", "session"],
"type": "yii2-extension", "type": "yii2-extension",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"support": { "support": {

2
framework/yii/caching/Cache.php

@ -58,7 +58,7 @@ abstract class Cache extends Component implements \ArrayAccess
* if you don't want to use key prefix. It is recommended that you explicitly set this property to some * if you don't want to use key prefix. It is recommended that you explicitly set this property to some
* static value if the cached data needs to be shared among multiple applications. * static value if the cached data needs to be shared among multiple applications.
* *
* To ensure interoperability, only use alphanumeric characters should be used. * To ensure interoperability, only alphanumeric characters should be used.
*/ */
public $keyPrefix; public $keyPrefix;
/** /**

Loading…
Cancel
Save