From 9f36981134afde4aeb8fbc14122a71dd1fe745e3 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Tue, 28 Jul 2015 09:24:24 +0300 Subject: [PATCH 01/36] Added link to guide --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 92442afc8..91e8a01ce 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ you to store active records in redis. For license information check the [LICENSE](LICENSE.md)-file. +Documentation is at [docs/guide/README.md](docs/guide/README.md). + [![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-redis/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-redis) [![Total Downloads](https://poser.pugx.org/yiisoft/yii2-redis/downloads.png)](https://packagist.org/packages/yiisoft/yii2-redis) [![Build Status](https://travis-ci.org/yiisoft/yii2-redis.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-redis) From f2ad88aef28490328766b29397ddfd496a1c80a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=95=83=E5=B7=A1=E6=B4=8B=E8=89=A6=E3=8A=A3?= Date: Thu, 6 Aug 2015 21:48:32 +0800 Subject: [PATCH 02/36] add guide-zh-CN --- docs/guide-zh-CN/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docs/guide-zh-CN/README.md diff --git a/docs/guide-zh-CN/README.md b/docs/guide-zh-CN/README.md new file mode 100644 index 000000000..f33ec62e9 --- /dev/null +++ b/docs/guide-zh-CN/README.md @@ -0,0 +1,24 @@ +Yii 2 Redis Cache, Session 和 ActiveRecord +=============================================== + +此扩展为 Yii2 framework 提供了 [redis](http://redis.io/) key-value 存储的支持。 +包含了一个 `Cache` 和 `Session` 存储句柄并且实现了 `ActiveRecord` 模式,允许 +你存储 active records 到 redis 中。 + + +入门指南 +--------------- + +* [安装](installation.md) + +用法 +----- + +* [ActiveRecord 的使用](usage-ar.md) +* [直接使用命令](usage-commands.md) + +附加主题 +----------------- + +* [Cache 组件的使用](topics-cache.md) +* [Session 组件的使用](topics-session.md) From aba5ffa96ac12f7f715c6c2b6cb907aa7eb5c810 Mon Sep 17 00:00:00 2001 From: Alexander Kochetov Date: Tue, 11 Aug 2015 02:23:13 +0300 Subject: [PATCH 03/36] Refactored \yii\redis\Cache::init --- Cache.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Cache.php b/Cache.php index 995a0d7d8..3e6a82496 100644 --- a/Cache.php +++ b/Cache.php @@ -76,17 +76,7 @@ class Cache extends \yii\caching\Cache public function init() { parent::init(); - if (is_string($this->redis)) { - $this->redis = Yii::$app->get($this->redis); - } elseif (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("Cache::redis must be either a Redis connection instance or the application component ID of a Redis connection."); - } + $this->redis = Instance::ensure($this->redis, Connection::className()); } /** From 5772e2dcb77466babbdf58ae9943c5e692bd5ce1 Mon Sep 17 00:00:00 2001 From: Alexander Kochetov Date: Tue, 11 Aug 2015 02:25:00 +0300 Subject: [PATCH 04/36] Fixed forgotten import --- Cache.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Cache.php b/Cache.php index 3e6a82496..44e130f46 100644 --- a/Cache.php +++ b/Cache.php @@ -9,6 +9,7 @@ use Yii; use yii\base\InvalidConfigException; +use yii\di\Instance; /** * Redis Cache implements a cache application component based on [redis](http://redis.io/) key-value store. From 021c997f10ca395598303a76e44bc007e4017760 Mon Sep 17 00:00:00 2001 From: Alexander Kochetov Date: Tue, 11 Aug 2015 02:27:17 +0300 Subject: [PATCH 05/36] Removed excess import --- Cache.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Cache.php b/Cache.php index 44e130f46..761a7b9bf 100644 --- a/Cache.php +++ b/Cache.php @@ -8,7 +8,6 @@ namespace yii\redis; use Yii; -use yii\base\InvalidConfigException; use yii\di\Instance; /** From 33f1b952f7f3d43be171b9cf025819c8e25b731b Mon Sep 17 00:00:00 2001 From: Alexander Kochetov Date: Tue, 11 Aug 2015 04:25:39 +0300 Subject: [PATCH 06/36] Typo fixed --- Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Connection.php b/Connection.php index 38e884598..a004d4a1b 100644 --- a/Connection.php +++ b/Connection.php @@ -363,7 +363,7 @@ public function __call($name, $params) * * See [redis protocol description](http://redis.io/topics/protocol) * for details on the mentioned reply types. - * @trows Exception for commands that return [error reply](http://redis.io/topics/protocol#error-reply). + * @throws Exception for commands that return [error reply](http://redis.io/topics/protocol#error-reply). */ public function executeCommand($name, $params = []) { From 5357c77e8ca019e022e07c087544aa02fe9bfc41 Mon Sep 17 00:00:00 2001 From: Anton Ermolovich Date: Tue, 11 Aug 2015 12:42:45 +0300 Subject: [PATCH 07/36] Fix error 'Invalid argument supplied for foreach()' for method all() in ActiveQuery --- ActiveQuery.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ActiveQuery.php b/ActiveQuery.php index f52dc0b1a..ecff9db79 100644 --- a/ActiveQuery.php +++ b/ActiveQuery.php @@ -116,6 +116,9 @@ public function all($db = null) { // TODO add support for orderBy $data = $this->executeScript($db, 'All'); + if (empty($data)) { + return []; + } $rows = []; foreach ($data as $dataRow) { $row = []; From 77b21a6cfde63f1aa47a9199df6d012eba88b2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=95=83=E5=B7=A1=E6=B4=8B=E8=89=A6=E3=8A=A3?= Date: Tue, 22 Sep 2015 17:08:47 +0800 Subject: [PATCH 08/36] Add zh-CN translation --- docs/guide-zh-CN/README.md | 12 +++--- docs/guide-zh-CN/installation.md | 42 ++++++++++++++++++++ docs/guide-zh-CN/topics-cache.md | 37 +++++++++++++++++ docs/guide-zh-CN/topics-session.md | 37 +++++++++++++++++ docs/guide-zh-CN/usage-ar.md | 64 ++++++++++++++++++++++++++++++ docs/guide-zh-CN/usage-commands.md | 23 +++++++++++ 6 files changed, 209 insertions(+), 6 deletions(-) create mode 100644 docs/guide-zh-CN/installation.md create mode 100644 docs/guide-zh-CN/topics-cache.md create mode 100644 docs/guide-zh-CN/topics-session.md create mode 100644 docs/guide-zh-CN/usage-ar.md create mode 100644 docs/guide-zh-CN/usage-commands.md diff --git a/docs/guide-zh-CN/README.md b/docs/guide-zh-CN/README.md index f33ec62e9..e317ae368 100644 --- a/docs/guide-zh-CN/README.md +++ b/docs/guide-zh-CN/README.md @@ -1,9 +1,9 @@ -Yii 2 Redis Cache, Session 和 ActiveRecord +Yii 2 Redis 缓存,会话和活动记录 =============================================== -此扩展为 Yii2 framework 提供了 [redis](http://redis.io/) key-value 存储的支持。 +此扩展为 Yii2 framework 提供了 [redis](http://redis.io/) 键-值存储的支持。 包含了一个 `Cache` 和 `Session` 存储句柄并且实现了 `ActiveRecord` 模式,允许 -你存储 active records 到 redis 中。 +你存储活动记录到 redis 中。 入门指南 @@ -14,11 +14,11 @@ Yii 2 Redis Cache, Session 和 ActiveRecord 用法 ----- -* [ActiveRecord 的使用](usage-ar.md) +* [活动记录的使用](usage-ar.md) * [直接使用命令](usage-commands.md) 附加主题 ----------------- -* [Cache 组件的使用](topics-cache.md) -* [Session 组件的使用](topics-session.md) +* [缓存组件的使用](topics-cache.md) +* [会话组件的使用](topics-session.md) diff --git a/docs/guide-zh-CN/installation.md b/docs/guide-zh-CN/installation.md new file mode 100644 index 000000000..449e69722 --- /dev/null +++ b/docs/guide-zh-CN/installation.md @@ -0,0 +1,42 @@ +安装 +============ + +## 需求 + +redis 2.6.12 版本是所有部件正常工作所必需的。 + +## 获取 Composer 安装包 + +安装此扩展的首选方式是通过 [composer](http://getcomposer.org/download/)。 + +可以运行 + +``` +php composer.phar require --prefer-dist yiisoft/yii2-redis +``` + +或者添加 + +```json +"yiisoft/yii2-redis": "~2.0.0" +``` + +在 `composer.json` 文件中的必要部分。 + +## 配置应用程序 + +使用此扩展时,需要在你的应用程序配置中配置 Connection 类: + +```php +return [ + //.... + 'components' => [ + 'redis' => [ + 'class' => 'yii\redis\Connection', + 'hostname' => 'localhost', + 'port' => 6379, + 'database' => 0, + ], + ] +]; +``` diff --git a/docs/guide-zh-CN/topics-cache.md b/docs/guide-zh-CN/topics-cache.md new file mode 100644 index 000000000..a1d6f5331 --- /dev/null +++ b/docs/guide-zh-CN/topics-cache.md @@ -0,0 +1,37 @@ +缓存组件的使用 +========================= + +为了使用 `Cache` 组件,如 [安装](installation.md) 章节中所描述的,除了配置连接, +你也需要配置 `yii\redis\Cache` 中的 `cache` 组件: + +```php +return [ + //.... + 'components' => [ + // ... + 'cache' => [ + 'class' => 'yii\redis\Cache', + ], + ] +]; +``` + +如果你只使用 redis 缓存(即,不使用它的活动记录或者会话),您还可以配置缓存组件内的 +连接参数(在这种情况下,不需要配置连接应用程序的组件): + +```php +return [ + //.... + 'components' => [ + // ... + 'cache' => [ + 'class' => 'yii\redis\Cache', + 'redis' => [ + 'hostname' => 'localhost', + 'port' => 6379, + 'database' => 0, + ], + ], + ] +]; +``` diff --git a/docs/guide-zh-CN/topics-session.md b/docs/guide-zh-CN/topics-session.md new file mode 100644 index 000000000..80ef0a987 --- /dev/null +++ b/docs/guide-zh-CN/topics-session.md @@ -0,0 +1,37 @@ +会话组件的使用 +=========================== + +为了使用 `Session` 组件,如 [安装](installation.md) 章节中所描述的,除了配置连接, +你也需要配置 `yii\redis\Session` 中的 `session` 组件: + +```php +return [ + //.... + 'components' => [ + // ... + 'session' => [ + 'class' => 'yii\redis\Session', + ], + ] +]; +``` + +如果你只使用 redis 会话(即,不使用它的活动记录或者缓存),您还可以配置会话组件内的 +连接参数(在这种情况下,不需要配置连接应用程序的组件): + +```php +return [ + //.... + 'components' => [ + // ... + 'session' => [ + 'class' => 'yii\redis\Session', + 'redis' => [ + 'hostname' => 'localhost', + 'port' => 6379, + 'database' => 0, + ], + ], + ] +]; +``` diff --git a/docs/guide-zh-CN/usage-ar.md b/docs/guide-zh-CN/usage-ar.md new file mode 100644 index 000000000..0b5022e80 --- /dev/null +++ b/docs/guide-zh-CN/usage-ar.md @@ -0,0 +1,64 @@ +活动记录的使用 +====================== + +对于如何使用 yii 的活动记录一般信息请参阅 [指南](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md)。 + +定义一个 redis 活动记录类,你的记录类需要继承自 [[yii\redis\ActiveRecord]] 并且 +至少实现 `attributes()` 方法来定义记录的属性。 +一个没有指定默认值,默认为 `id` 的主键可以通过 [[yii\redis\ActiveRecord::primaryKey()]] 定义。 +主键是属性中必要的一部分,所以请确保你有一个 `id` 属性定义的, +如果你没有指定自己的主键。 + +以下是一个 `Customer` 的实例模型: + +```php +class Customer extends \yii\redis\ActiveRecord +{ + /** + * @return array 此记录的属性列表 + */ + public function attributes() + { + return ['id', 'name', 'address', 'registration_date']; + } + + /** + * @return ActiveQuery 定义一个关联到 Order 的记录(可以在其它数据库中,例如 elasticsearch 或者 sql) + */ + public function getOrders() + { + return $this->hasMany(Order::className(), ['customer_id' => 'id']); + } + + /** + * 定义一个修改 `$query` 的范围,当返回有效(status = 1)客户。 + */ + public static function active($query) + { + $query->andWhere(['status' => 1]); + } +} +``` + +redis 活动记录的一般用法和数据库活动记录非常相似,正如 +[指南](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md) 中所描述的。 +它支持相同的界面和功能,除了以下限制: + +- redis 不支持 SQL 查询的 API 仅限于以下方法: + `where()`,`limit()`,`offset()`,`orderBy()` 和 `indexBy()`。 + (orderBy() 尚未实现:[#1305](https://github.com/yiisoft/yii2/issues/1305)) +- `via`-关系不能通过在 redis 中没有的表定义。你只能通过其他记录来定义关系。 + +另外,也可以定义从 redis 的活动记录关系到正常的活动记录类,反之亦然。 + +使用实例: + +```php +$customer = new Customer(); +$customer->attributes = ['name' => 'test']; +$customer->save(); +echo $customer->id; // 如果没有明确设置 id 会自动递增 + +$customer = Customer::find()->where(['name' => 'test'])->one(); // 通过 query 查找 +$customer = Customer::find()->active()->all(); // 通过 query 查找全部(使用 `active` 范围) +``` diff --git a/docs/guide-zh-CN/usage-commands.md b/docs/guide-zh-CN/usage-commands.md new file mode 100644 index 000000000..ffab5814f --- /dev/null +++ b/docs/guide-zh-CN/usage-commands.md @@ -0,0 +1,23 @@ +直接使用命令行 +======================= + +Redis 有很多可以直接从连接中使用的有用的命令。在配置应用程序后, +如 [安装](installation.md) 所示,连接可以像下面这样获取: + +```php +$redis = Yii::$app->redis; +``` + +完成之后可以执行如下命令。最通用的方法是使用 `executeCommand` 方法: + +```php +$result = $redis->executeCommand('hmset', ['test_collection', 'key1', 'val1', 'key2', 'val2']); +``` + +每个命令都有相应的快捷方式支持,所以可以像下面这样代替以上的命令: + +```php +$result = $redis->hmset(['test_collection', 'key1', 'val1', 'key2', 'val2']); +``` + +可用命令列表和他们的参数可参阅 [http://redis.io/commands](http://redis.io/commands)。 \ No newline at end of file From 167bec3613db51fd543c63b3f8aff30516d40bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=95=83=E5=B7=A1=E6=B4=8B=E8=89=A6=E3=8A=A3?= Date: Tue, 22 Sep 2015 17:11:55 +0800 Subject: [PATCH 09/36] edit usage-ar --- docs/guide-zh-CN/usage-ar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide-zh-CN/usage-ar.md b/docs/guide-zh-CN/usage-ar.md index 0b5022e80..d662bac8f 100644 --- a/docs/guide-zh-CN/usage-ar.md +++ b/docs/guide-zh-CN/usage-ar.md @@ -31,7 +31,7 @@ class Customer extends \yii\redis\ActiveRecord } /** - * 定义一个修改 `$query` 的范围,当返回有效(status = 1)客户。 + * 定义一个修改 `$query` 的范围返回有效(status = 1)的客户。 */ public static function active($query) { From 51bee048fe5417dc453a5ae86b147e4a5f9cc53d Mon Sep 17 00:00:00 2001 From: Daniel Gomez Pan Date: Tue, 29 Sep 2015 12:50:19 +0200 Subject: [PATCH 10/36] Add editorconfig [skip ci] --- .editorconfig | 14 ++++++++++++++ .gitattributes | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..257221d23 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes index 59ea3d79b..08476fafc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +1,9 @@ # Ignore all test and documentation for archive +/.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore /.scrutinizer.yml export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore /tests export-ignore -/docs export-ignore \ No newline at end of file +/docs export-ignore From 2ec0b757639d86a3f49b05098a6660d917bb4d02 Mon Sep 17 00:00:00 2001 From: mirocow Date: Mon, 12 Oct 2015 15:45:40 +0300 Subject: [PATCH 11/36] Fixes #37: Fixed detection of open socket --- CHANGELOG.md | 2 +- Connection.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a69acb95f..5fb3de6a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,9 @@ Yii Framework 2 redis extension Change Log 2.0.5 under development ----------------------- +- Bug #37: Fixed detection of open socket (mirocow) - Chg #14: Added missing `BLPOP` to `$redisCommands` (samdark) - 2.0.4 May 10, 2015 ------------------ diff --git a/Connection.php b/Connection.php index a004d4a1b..91f6fb2f2 100644 --- a/Connection.php +++ b/Connection.php @@ -225,7 +225,7 @@ class Connection extends Component /** * @var resource redis socket connection */ - private $_socket; + private $_socket = false; /** @@ -245,7 +245,7 @@ public function __sleep() */ public function getIsActive() { - return $this->_socket !== null; + return $this->_socket !== false; } /** @@ -255,7 +255,7 @@ public function getIsActive() */ public function open() { - if ($this->_socket !== null) { + if ($this->_socket !== false) { return; } $connection = ($this->unixSocket ?: $this->hostname . ':' . $this->port) . ', database=' . $this->database; @@ -288,7 +288,7 @@ public function open() */ public function close() { - if ($this->_socket !== null) { + if ($this->_socket !== false) { $connection = ($this->unixSocket ?: $this->hostname . ':' . $this->port) . ', database=' . $this->database; \Yii::trace('Closing DB connection: ' . $connection, __METHOD__); $this->executeCommand('QUIT'); From 3c8c6a42c0177a244b5bb878d60c3ad1d2d14f96 Mon Sep 17 00:00:00 2001 From: Evgeniy Tkachenko Date: Fri, 4 Dec 2015 12:20:37 +0300 Subject: [PATCH 12/36] Update Session.php --- Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Session.php b/Session.php index 70a74b7dc..0ed3a30f0 100644 --- a/Session.php +++ b/Session.php @@ -116,7 +116,7 @@ public function readSession($id) { $data = $this->redis->executeCommand('GET', [$this->calculateKey($id)]); - return $data === false ? '' : $data; + return $data === false || $data === null ? '' : $data; } /** From fb83a885095b7ec3ce90ecdc3535b290a9aaa564 Mon Sep 17 00:00:00 2001 From: Evgeniy Tkachenko Date: Fri, 4 Dec 2015 12:25:29 +0300 Subject: [PATCH 13/36] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb3de6a3..d64ff15d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Yii Framework 2 redis extension Change Log ----------------------- - Bug #37: Fixed detection of open socket (mirocow) +- Bug #46: Fixed bug to execute session_regenerate_id in PHP 7.0 (githubjeka) - Chg #14: Added missing `BLPOP` to `$redisCommands` (samdark) 2.0.4 May 10, 2015 From 28c9db985b973fc53eec5c1ef024d96577cc2e70 Mon Sep 17 00:00:00 2001 From: Daniel Gomez Pan Date: Mon, 7 Dec 2015 07:43:02 +0100 Subject: [PATCH 14/36] Update travis --- .travis.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index def49ecea..791d171f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,18 +6,16 @@ php: - 5.6 - 7.0 - hhvm - - hhvm-nightly services: - redis-server # run build against hhvm but allow them to fail # http://docs.travis-ci.com/user/build-configuration/#Rows-That-are-Allowed-To-Fail -matrix: - fast_finish: true - allow_failures: - - php: hhvm-nightly - - php: 7.0 +#matrix: +# fast_finish: true +# allow_failures: +# - php: 7.0 # faster builds on new travis setup not using sudo sudo: false @@ -29,7 +27,7 @@ cache: install: - travis_retry composer self-update && composer --version - - travis_retry composer global require "fxp/composer-asset-plugin:~1.0.0" + - travis_retry composer global require "fxp/composer-asset-plugin:~1.1.1" - export PATH="$HOME/.composer/vendor/bin:$PATH" - travis_retry composer install --prefer-dist --no-interaction From 08ea23a4944c3089eb207da33c26dd3c6fb18da0 Mon Sep 17 00:00:00 2001 From: Daniel Gomez Pan Date: Mon, 7 Dec 2015 12:55:25 +0100 Subject: [PATCH 15/36] Remove block comment [skip ci] --- .travis.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 791d171f1..e095aa6c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,6 @@ php: services: - redis-server -# run build against hhvm but allow them to fail -# http://docs.travis-ci.com/user/build-configuration/#Rows-That-are-Allowed-To-Fail -#matrix: -# fast_finish: true -# allow_failures: -# - php: 7.0 - # faster builds on new travis setup not using sudo sudo: false From b19fdb994ce4ccda6438dd4ce8bf96bf147eedbf Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 23 Dec 2015 16:45:57 +0300 Subject: [PATCH 16/36] Fixes #49 --- docs/guide/usage-commands.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/usage-commands.md b/docs/guide/usage-commands.md index 2b2f07a7e..5af2d384f 100644 --- a/docs/guide/usage-commands.md +++ b/docs/guide/usage-commands.md @@ -17,7 +17,7 @@ $result = $redis->executeCommand('hmset', ['test_collection', 'key1', 'val1', 'k There are shortcuts available for each command supported so insted of the above it can be used as follows: ```php -$result = $redis->hmset(['test_collection', 'key1', 'val1', 'key2', 'val2']); +$result = $redis->hmset('test_collection', 'key1', 'val1', 'key2', 'val2'); ``` -For a list of available commands and their parameters see [http://redis.io/commands](http://redis.io/commands). \ No newline at end of file +For a list of available commands and their parameters see [http://redis.io/commands](http://redis.io/commands). From 36711fd2dac05a0c3e430b2e041fb0422521fb10 Mon Sep 17 00:00:00 2001 From: Nobuo Kihara Date: Thu, 24 Dec 2015 20:23:30 +0900 Subject: [PATCH 17/36] docs/guide-ja/usage-commands.md updated [ci skip] --- docs/guide-ja/usage-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide-ja/usage-commands.md b/docs/guide-ja/usage-commands.md index 3fa8b40e4..9fd3bedd2 100644 --- a/docs/guide-ja/usage-commands.md +++ b/docs/guide-ja/usage-commands.md @@ -18,7 +18,7 @@ $result = $redis->executeCommand('hmset', ['test_collection', 'key1', 'val1', 'k サポートされているコマンドのそれぞれに対してショートカットが利用できますので、上記の代りに次のようにすることも出来ます。 ```php -$result = $redis->hmset(['test_collection', 'key1', 'val1', 'key2', 'val2']); +$result = $redis->hmset('test_collection', 'key1', 'val1', 'key2', 'val2'); ``` 利用できるコマンドとそのパラメータについては、[http://redis.io/commands](http://redis.io/commands) のリストを参照してください。 From d62f4f3150211c8e21717cf8370b2dc6eb9a2fd9 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Tue, 1 Mar 2016 04:10:20 +0100 Subject: [PATCH 18/36] adjusted makefile --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 13a96ae36..b6dd0e982 100644 --- a/Makefile +++ b/Makefile @@ -5,14 +5,16 @@ REDIS_VERSION=3.0.0 PHP_VERSION=php-5.6.8 YII_VERSION=dev-master +# ensure all the configuration variables above are in environment of the shell commands below +export help: @echo "make test - run phpunit tests using a docker environment" @echo "make clean - stop docker and remove container" test: docker adjust-config - composer require "yiisoft/yii2:${YII_VERSION}" --prefer-dist - composer install --prefer-dist + #composer require "yiisoft/yii2:${YII_VERSION}" --prefer-dist + #composer install --prefer-dist docker run --rm=true -v $(shell pwd):/opt/test --link $(shell cat tests/dockerids/redis):redis yiitest/php:${PHP_VERSION} phpunit --verbose --color adjust-config: From 1d5cb617fd89f3bd48ca2d1e80e30119b5ee3068 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Tue, 1 Mar 2016 04:20:20 +0100 Subject: [PATCH 19/36] cleanup and phpdoc --- ActiveQuery.php | 4 ++-- ActiveRecord.php | 2 +- Connection.php | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ActiveQuery.php b/ActiveQuery.php index f52dc0b1a..3e73ac357 100644 --- a/ActiveQuery.php +++ b/ActiveQuery.php @@ -307,7 +307,7 @@ public function scalar($attribute, $db = null) * @param string $type the type of the script to generate * @param string $columnName * @throws NotSupportedException - * @return array|bool|null|string + * @return array|boolean|null|string */ protected function executeScript($db, $type, $columnName = null) { @@ -363,7 +363,7 @@ protected function executeScript($db, $type, $columnName = null) * If this parameter is not given, the `db` application component will be used. * @param string $type the type of the script to generate * @param string $columnName - * @return array|bool|null|string + * @return array|boolean|null|string * @throws \yii\base\InvalidParamException * @throws \yii\base\NotSupportedException */ diff --git a/ActiveRecord.php b/ActiveRecord.php index 845e5a098..2452fee8e 100644 --- a/ActiveRecord.php +++ b/ActiveRecord.php @@ -46,7 +46,7 @@ class ActiveRecord extends BaseActiveRecord */ public static function getDb() { - return \Yii::$app->get('redis'); + return Yii::$app->get('redis'); } /** diff --git a/Connection.php b/Connection.php index 91f6fb2f2..c41331ab5 100644 --- a/Connection.php +++ b/Connection.php @@ -235,7 +235,6 @@ class Connection extends Component public function __sleep() { $this->close(); - return array_keys(get_object_vars($this)); } @@ -351,7 +350,7 @@ public function __call($name, $params) * * @param string $name the name of the command * @param array $params list of parameters for the command - * @return array|bool|null|string Dependent on the executed command this method + * @return array|boolean|null|string Dependent on the executed command this method * will return different data types: * * - `true` for commands that return "status reply" with the message `'OK'` or `'PONG'`. From fab6866e7ad80d2114578b0136c86e133889bfb7 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Tue, 1 Mar 2016 04:28:26 +0100 Subject: [PATCH 20/36] added failing test for #22 --- tests/ActiveRecordTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/ActiveRecordTest.php b/tests/ActiveRecordTest.php index ad9593c59..cb7930bb7 100644 --- a/tests/ActiveRecordTest.php +++ b/tests/ActiveRecordTest.php @@ -407,4 +407,14 @@ public function testAutoIncrement() $this->assertNotNull($customer); $this->assertEquals('user6', $customer->name); } + + public function testEscapeData() + { + $customer = new Customer(); + $customer->email = "the People's Republic of China"; + $customer->save(false); + + $c = Customer::findOne(['email' => "the People's Republic of China"]); + $this->assertSame("the People's Republic of China", $c->email); + } } From d37c989a62503588b93ee9d402f0c4628b67eaaa Mon Sep 17 00:00:00 2001 From: Zhao vistart Date: Thu, 6 Aug 2015 10:18:27 +0800 Subject: [PATCH 21/36] Fix the escape bug. Fix the escape bug. See detail in https://github.com/yiisoft/yii2-redis/issues/22 fixes #22 close #27 --- CHANGELOG.md | 1 + LuaScriptBuilder.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d64ff15d6..2b440494a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 redis extension Change Log 2.0.5 under development ----------------------- +- Bug #22: Fixed string escaping issue in LuaScriptBuilder (vistart) - Bug #37: Fixed detection of open socket (mirocow) - Bug #46: Fixed bug to execute session_regenerate_id in PHP 7.0 (githubjeka) - Chg #14: Added missing `BLPOP` to `$redisCommands` (samdark) diff --git a/LuaScriptBuilder.php b/LuaScriptBuilder.php index 2ba81116f..bc6ca02ed 100644 --- a/LuaScriptBuilder.php +++ b/LuaScriptBuilder.php @@ -215,7 +215,7 @@ private function quoteValue($str) return $str; } - return "'" . addcslashes(str_replace("'", "\\'", $str), "\000\n\r\\\032") . "'"; + return "'" . addcslashes($str, "\000\n\r\\\032\047") . "'"; } /** From 1cb19d1ba76bd6b85ac8b543d80c7d572b0ba7bd Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Tue, 1 Mar 2016 04:42:58 +0100 Subject: [PATCH 22/36] test find on empty DB --- tests/ActiveRecordTest.php | 11 +++++++++++ tests/RedisCacheTest.php | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/ActiveRecordTest.php b/tests/ActiveRecordTest.php index cb7930bb7..5cc25afa0 100644 --- a/tests/ActiveRecordTest.php +++ b/tests/ActiveRecordTest.php @@ -417,4 +417,15 @@ public function testEscapeData() $c = Customer::findOne(['email' => "the People's Republic of China"]); $this->assertSame("the People's Republic of China", $c->email); } + + public function testFindEmptyWith() + { + Order::getDb()->flushdb(); + $orders = Order::find() + ->where(['total' => 100000]) + ->orWhere(['total' => 1]) + ->with('customer') + ->all(); + $this->assertEquals([], $orders); + } } diff --git a/tests/RedisCacheTest.php b/tests/RedisCacheTest.php index 631fb44f5..ea745f24b 100644 --- a/tests/RedisCacheTest.php +++ b/tests/RedisCacheTest.php @@ -20,7 +20,7 @@ class RedisCacheTest extends CacheTestCase */ protected function getCacheInstance() { - $databases = self::getParam('databases'); + $databases = TestCase::getParam('databases'); $params = isset($databases['redis']) ? $databases['redis'] : null; if ($params === null) { $this->markTestSkipped('No redis server connection configured.'); From bb0cd7c290fed9fc4993e600dcaf089929a8379d Mon Sep 17 00:00:00 2001 From: hugh-lee <525803178@qq.com> Date: Mon, 31 Aug 2015 14:59:28 +0800 Subject: [PATCH 23/36] add socketClientFlags close #31 --- CHANGELOG.md | 1 + Connection.php | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b440494a..2f7ccb0fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Yii Framework 2 redis extension Change Log - Bug #22: Fixed string escaping issue in LuaScriptBuilder (vistart) - Bug #37: Fixed detection of open socket (mirocow) - Bug #46: Fixed bug to execute session_regenerate_id in PHP 7.0 (githubjeka) +- Enh #31: Added `Connection::$socketClientFlags` property for connection flags to be passed to `stream_socket_client()` (hugh-lee) - Chg #14: Added missing `BLPOP` to `$redisCommands` (samdark) 2.0.4 May 10, 2015 diff --git a/Connection.php b/Connection.php index c41331ab5..709ea3133 100644 --- a/Connection.php +++ b/Connection.php @@ -76,6 +76,13 @@ class Connection extends Component * @var float timeout to use for redis socket when reading and writing data. If not set the php default value will be used. */ public $dataTimeout = null; + /** + * @var integer Bitmask field which may be set to any combination of connection flags passed to [stream_socket_client()](http://php.net/manual/en/function.stream-socket-client.php). + * Currently the select of connection flags is limited to `STREAM_CLIENT_CONNECT` (default), `STREAM_CLIENT_ASYNC_CONNECT` and `STREAM_CLIENT_PERSISTENT`. + * @see http://php.net/manual/en/function.stream-socket-client.php + * @since 2.0.5 + */ + public $socketClientFlags = STREAM_CLIENT_CONNECT; /** * @var array List of available redis commands http://redis.io/commands */ @@ -263,7 +270,8 @@ public function open() $this->unixSocket ? 'unix://' . $this->unixSocket : 'tcp://' . $this->hostname . ':' . $this->port, $errorNumber, $errorDescription, - $this->connectionTimeout ? $this->connectionTimeout : ini_get("default_socket_timeout") + $this->connectionTimeout ? $this->connectionTimeout : ini_get("default_socket_timeout"), + $this->socketClientFlags ); if ($this->_socket) { if ($this->dataTimeout !== null) { From 305060bfb51cd06ce147ad5c5f10baff1e264dc9 Mon Sep 17 00:00:00 2001 From: leadermt Date: Wed, 9 Mar 2016 11:34:08 +0300 Subject: [PATCH 24/36] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b589d9f07..6255eb2f4 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "yiisoft/yii2-redis", + "name": "leadermt/yii2-redis", "description": "Redis Cache, Session and ActiveRecord for the Yii framework", "keywords": ["yii2", "redis", "active-record", "cache", "session"], "type": "yii2-extension", From f4c9967aad7e49e06e6309762268faf99b68fbe9 Mon Sep 17 00:00:00 2001 From: leadermt Date: Wed, 9 Mar 2016 17:17:59 +0300 Subject: [PATCH 25/36] Update Connection.php --- Connection.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Connection.php b/Connection.php index 709ea3133..d7c1882e6 100644 --- a/Connection.php +++ b/Connection.php @@ -227,6 +227,13 @@ class Connection extends Component 'ZREVRANK', // key member Determine the index of a member in a sorted set, with scores ordered from high to low 'ZSCORE', // key member Get the score associated with the given member in a sorted set 'ZUNIONSTORE', // destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] Add multiple sorted sets and store the resulting sorted set in a new key + + 'GEOADD', // key longitude latitude member [longitude latitude member ...] Add point + 'GEODIST', // key member1 member2 [unit] Return the distance between two members + 'GEOHASH', // key member [member ...] Return valid Geohash strings + 'GEOPOS', // key member [member ...] Return the positions (longitude,latitude) + 'GEORADIUS', // key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] Return the members + 'GEORADIUSBYMEMBER', // key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] ]; /** From 57452a5ebf9d845be2d66248edf2fa59f868627c Mon Sep 17 00:00:00 2001 From: leadermt Date: Wed, 9 Mar 2016 18:24:36 +0300 Subject: [PATCH 26/36] Update Connection.php --- Connection.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Connection.php b/Connection.php index d7c1882e6..a3894fbce 100644 --- a/Connection.php +++ b/Connection.php @@ -227,7 +227,6 @@ class Connection extends Component 'ZREVRANK', // key member Determine the index of a member in a sorted set, with scores ordered from high to low 'ZSCORE', // key member Get the score associated with the given member in a sorted set 'ZUNIONSTORE', // destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] Add multiple sorted sets and store the resulting sorted set in a new key - 'GEOADD', // key longitude latitude member [longitude latitude member ...] Add point 'GEODIST', // key member1 member2 [unit] Return the distance between two members 'GEOHASH', // key member [member ...] Return valid Geohash strings From a00d14463ac06c2430112e563345a989466292d9 Mon Sep 17 00:00:00 2001 From: leadermt Date: Wed, 9 Mar 2016 18:33:17 +0300 Subject: [PATCH 27/36] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6255eb2f4..b589d9f07 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "leadermt/yii2-redis", + "name": "yiisoft/yii2-redis", "description": "Redis Cache, Session and ActiveRecord for the Yii framework", "keywords": ["yii2", "redis", "active-record", "cache", "session"], "type": "yii2-extension", From 7fd93ff3847e765964c8c83b7e3eed0281078916 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Thu, 17 Mar 2016 05:11:03 +0100 Subject: [PATCH 28/36] release version 2.0.5 --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f7ccb0fb..fa2e133ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,16 @@ Yii Framework 2 redis extension Change Log ========================================== -2.0.5 under development ------------------------ +2.0.5 March 17, 2016 +-------------------- - Bug #22: Fixed string escaping issue in LuaScriptBuilder (vistart) - Bug #37: Fixed detection of open socket (mirocow) - Bug #46: Fixed bug to execute session_regenerate_id in PHP 7.0 (githubjeka) - Enh #31: Added `Connection::$socketClientFlags` property for connection flags to be passed to `stream_socket_client()` (hugh-lee) -- Chg #14: Added missing `BLPOP` to `$redisCommands` (samdark) +- Chg #14: Added missing `BLPOP` command to `$redisCommands` (samdark) +- Chg #61: Added missing `GEO*` commands to `$redisCommands` (leadermt) + 2.0.4 May 10, 2015 ------------------ From 0512be29cd214a9345bc0bc7883649138f5d5d25 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Thu, 17 Mar 2016 05:11:13 +0100 Subject: [PATCH 29/36] prepare for next release --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa2e133ad..063467091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Yii Framework 2 redis extension Change Log ========================================== +2.0.6 under development +----------------------- + +- no changes in this release. + + 2.0.5 March 17, 2016 -------------------- From 13596dbfc0a01870f9b581b3c99a22037c1132d8 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 21 Mar 2016 22:14:34 +0300 Subject: [PATCH 30/36] Added issue templates --- .gitattributes | 1 + .github/CONTRIBUTING.md | 7 +++++++ .github/ISSUE_TEMPLATE.md | 14 ++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 7 +++++++ 4 files changed, 29 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.gitattributes b/.gitattributes index 08476fafc..b5aa1bef7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ # Ignore all test and documentation for archive +/.github export-ignore /.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..b0924689b --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,7 @@ +Contributing to Yii2 +==================== + +- [Report an issue](docs/internals/report-an-issue.md) +- [Translate documentation or messages](docs/internals/translation-workflow.md) +- [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/) +- [Contribute to the core code or fix bugs](docs/internals/git-workflow.md) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..52ec8692f --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,14 @@ +### What steps will reproduce the problem? + +### What's expected? + +### What do you get instead? + + +### Additional info + +| Q | A +| ---------------- | --- +| Yii vesion | +| PHP version | +| Operating system | diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..968a845de --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +| Q | A +| ------------- | --- +| Is bugfix? | yes/no +| New feature? | yes/no +| Breaks BC? | yes/no +| Tests pass? | yes/no +| Fixed issues | comma-separated list of tickets # fixed by the PR, if any From d65431e5502a6827849a73787dbb749ccae65923 Mon Sep 17 00:00:00 2001 From: LightOfHeaveN Date: Wed, 23 Mar 2016 22:34:21 +0800 Subject: [PATCH 31/36] Update Connection.php using single quotes --- Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Connection.php b/Connection.php index a3894fbce..98bb52b2c 100644 --- a/Connection.php +++ b/Connection.php @@ -276,7 +276,7 @@ public function open() $this->unixSocket ? 'unix://' . $this->unixSocket : 'tcp://' . $this->hostname . ':' . $this->port, $errorNumber, $errorDescription, - $this->connectionTimeout ? $this->connectionTimeout : ini_get("default_socket_timeout"), + $this->connectionTimeout ? $this->connectionTimeout : ini_get('default_socket_timeout'), $this->socketClientFlags ); if ($this->_socket) { From 0072af9505644ad719e852a3d01ed9295ef4d23e Mon Sep 17 00:00:00 2001 From: LightOfHeaveN Date: Wed, 23 Mar 2016 22:48:09 +0800 Subject: [PATCH 32/36] with no need for type cast with the error number --- Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Connection.php b/Connection.php index 98bb52b2c..8d704e75d 100644 --- a/Connection.php +++ b/Connection.php @@ -291,7 +291,7 @@ public function open() } else { \Yii::error("Failed to open redis DB connection ($connection): $errorNumber - $errorDescription", __CLASS__); $message = YII_DEBUG ? "Failed to open redis DB connection ($connection): $errorNumber - $errorDescription" : 'Failed to open DB connection.'; - throw new Exception($message, $errorDescription, (int) $errorNumber); + throw new Exception($message, $errorDescription, $errorNumber); } } From d28911a005a02cd3b01940bb8e959813599b287a Mon Sep 17 00:00:00 2001 From: Andrey Kolobov Date: Thu, 7 Apr 2016 21:11:56 +0500 Subject: [PATCH 33/36] move connection from socket to phpredis --- .travis.yml | 3 + ActiveQuery.php | 51 ++++++++----- ActiveRecord.php | 30 ++++---- Cache.php | 20 ++--- Connection.php | 133 ++++++++++------------------------ Session.php | 2 +- tests/RedisConnectionTest.php | 16 ++-- tests/data/ar/Customer.php | 5 ++ 8 files changed, 108 insertions(+), 152 deletions(-) diff --git a/.travis.yml b/.travis.yml index e095aa6c4..3cf8224f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,9 @@ install: - travis_retry composer install --prefer-dist --no-interaction before_script: +# install phpredis extension. + - sh -c "git clone https://github.com/nicolasff/phpredis/ && cd phpredis && phpize && ./configure && make && sudo make install " > /dev/null + - echo "extension=redis.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - | if [ $TRAVIS_PHP_VERSION = '5.6' ]; then PHPUNIT_FLAGS="--coverage-clover=coverage.clover" diff --git a/ActiveQuery.php b/ActiveQuery.php index e9cae0b52..24b86d96e 100644 --- a/ActiveQuery.php +++ b/ActiveQuery.php @@ -119,16 +119,8 @@ public function all($db = null) if (empty($data)) { return []; } - $rows = []; - foreach ($data as $dataRow) { - $row = []; - $c = count($dataRow); - for ($i = 0; $i < $c;) { - $row[$dataRow[$i++]] = $dataRow[$i++]; - } + $rows = $this->parseList($data); - $rows[] = $row; - } if (!empty($rows)) { $models = $this->createModels($rows); if (!empty($this->with)) { @@ -161,11 +153,8 @@ public function one($db = null) if (empty($data)) { return null; } - $row = []; - $c = count($data); - for ($i = 0; $i < $c;) { - $row[$data[$i++]] = $data[$i++]; - } + $row = $this->parseRow($data); + if ($this->asArray) { $model = $row; } else { @@ -350,7 +339,10 @@ protected function executeScript($db, $type, $columnName = null) } // convert inCondition for one key - if (is_array($this->where) && isset($this->where[0]) && $this->where[0] == 'in' && count($this->where[1]) == 1) { + if (is_array($this->where) && isset($this->where[0]) && $this->where[0] == 'in' && count( + $this->where[1] + ) == 1 + ) { $this->where = [current($this->where[1]) => $this->where[2]]; } @@ -362,7 +354,7 @@ protected function executeScript($db, $type, $columnName = null) $method = 'build' . $type; $script = $db->getLuaScriptBuilder()->$method($this, $columnName); - return $db->executeCommand('EVAL', [$script, 0]); + return $db->executeCommand('EVAL', [$script]); } /** @@ -378,7 +370,7 @@ protected function executeScript($db, $type, $columnName = null) private function findByPk($db, $type, $columnName = null) { if (count($this->where) == 1) { - $pks = (array) reset($this->where); + $pks = (array)reset($this->where); } else { foreach ($this->where as $values) { if (is_array($values)) { @@ -491,4 +483,29 @@ private function findByPk($db, $type, $columnName = null) } throw new InvalidParamException('Unknown fetch type: ' . $type); } + + private function parseList($data) + { + $result = []; + foreach ($data as $list) { + $result[] = $this->parseRow($list); + } + + return $result; + } + + private function parseRow($row) + { + if (!isset($row[0])) { + return $row; + } + + $result = []; + $c = count($row); + + for ($i = 0; $i < $c;) { + $result[$row[$i++]] = $row[$i++]; + } + return $result; + } } diff --git a/ActiveRecord.php b/ActiveRecord.php index 49f654a43..2cfe7ccaf 100644 --- a/ActiveRecord.php +++ b/ActiveRecord.php @@ -126,20 +126,19 @@ public function insert($runValidation = true, $attributes = null) $key = static::keyPrefix() . ':a:' . static::buildKey($pk); // save attributes - $setArgs = [$key]; + $setArgs = []; foreach ($values as $attribute => $value) { // only insert attributes that are not null if ($value !== null) { if (is_bool($value)) { $value = (int) $value; } - $setArgs[] = $attribute; - $setArgs[] = $value; + $setArgs[$attribute] = $value; } } if (count($setArgs) > 1) { - $db->executeCommand('HMSET', $setArgs); + $db->executeCommand('HMSET', [$key, $setArgs]); } $changedAttributes = array_fill_keys(array_keys($values), null); @@ -174,8 +173,6 @@ public static function updateAll($attributes, $condition = null) $pk = static::buildKey($pk); $key = static::keyPrefix() . ':a:' . $pk; // save attributes - $delArgs = [$key]; - $setArgs = [$key]; foreach ($attributes as $attribute => $value) { if (isset($newPk[$attribute])) { $newPk[$attribute] = $value; @@ -184,10 +181,9 @@ public static function updateAll($attributes, $condition = null) if (is_bool($value)) { $value = (int) $value; } - $setArgs[] = $attribute; - $setArgs[] = $value; + $setArgs[$attribute] = $value; } else { - $delArgs[] = $attribute; + $delArgs = $attribute; } } $newPk = static::buildKey($newPk); @@ -195,22 +191,22 @@ public static function updateAll($attributes, $condition = null) // rename index if pk changed if ($newPk != $pk) { $db->executeCommand('MULTI'); - if (count($setArgs) > 1) { - $db->executeCommand('HMSET', $setArgs); + if (!empty($setArgs)) { + $db->executeCommand('HMSET', [$key, $setArgs]); } - if (count($delArgs) > 1) { - $db->executeCommand('HDEL', $delArgs); + if (!empty($delArgs)) { + $db->executeCommand('HDEL', [$key, $delArgs]); } $db->executeCommand('HSET', [static::keyPrefix(), $newPk, 0]); $db->executeCommand('HDEL', [static::keyPrefix(), $pk]); $db->executeCommand('RENAME', [$key, $newKey]); $db->executeCommand('EXEC'); } else { - if (count($setArgs) > 1) { - $db->executeCommand('HMSET', $setArgs); + if (!empty($setArgs)) { + $db->executeCommand('HMSET', [$key, $setArgs]); } - if (count($delArgs) > 1) { - $db->executeCommand('HDEL', $delArgs); + if (!empty($delArgs)) { + $db->executeCommand('HDEL', [$key, $delArgs]); } } $n++; diff --git a/Cache.php b/Cache.php index 761a7b9bf..11f13f2ca 100644 --- a/Cache.php +++ b/Cache.php @@ -107,7 +107,7 @@ protected function getValue($key) */ protected function getValues($keys) { - $response = $this->redis->executeCommand('MGET', $keys); + $response = $this->redis->executeCommand('MGET', [$keys]); $result = []; $i = 0; foreach ($keys as $key) { @@ -123,11 +123,11 @@ protected function getValues($keys) protected function setValue($key, $value, $expire) { if ($expire == 0) { - return (bool) $this->redis->executeCommand('SET', [$key, $value]); + return (bool) $this->redis->executeCommand('SETNX', [$key, $value]); } else { $expire = (int) ($expire * 1000); - return (bool) $this->redis->executeCommand('SET', [$key, $value, 'PX', $expire]); + return (bool) $this->redis->executeCommand('PSETEX', [$key, $expire, $value]); } } @@ -136,19 +136,13 @@ protected function setValue($key, $value, $expire) */ protected function setValues($data, $expire) { - $args = []; - foreach ($data as $key => $value) { - $args[] = $key; - $args[] = $value; - } - $failedKeys = []; if ($expire == 0) { - $this->redis->executeCommand('MSET', $args); + $this->redis->executeCommand('MSET', [$data]); } else { $expire = (int) ($expire * 1000); $this->redis->executeCommand('MULTI'); - $this->redis->executeCommand('MSET', $args); + $this->redis->executeCommand('MSET', [$data]); $index = []; foreach ($data as $key => $value) { $this->redis->executeCommand('PEXPIRE', [$key, $expire]); @@ -172,11 +166,11 @@ protected function setValues($data, $expire) protected function addValue($key, $value, $expire) { if ($expire == 0) { - return (bool) $this->redis->executeCommand('SET', [$key, $value, 'NX']); + return (bool) $this->redis->executeCommand('SETNX', [$key, $value]); } else { $expire = (int) ($expire * 1000); - return (bool) $this->redis->executeCommand('SET', [$key, $value, 'PX', $expire, 'NX']); + return (bool) $this->redis->executeCommand('PSETEX', [$key, $expire, $value]); } } diff --git a/Connection.php b/Connection.php index 9d2b66239..88343abf7 100644 --- a/Connection.php +++ b/Connection.php @@ -69,20 +69,13 @@ class Connection extends Component */ public $database = 0; /** - * @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: ini_get("default_socket_timeout") + * @var float timeout to use for connection to redis. */ - public $connectionTimeout = null; + public $connectionTimeout = 10; /** * @var float timeout to use for redis socket when reading and writing data. If not set the php default value will be used. */ public $dataTimeout = null; - /** - * @var integer Bitmask field which may be set to any combination of connection flags passed to [stream_socket_client()](http://php.net/manual/en/function.stream-socket-client.php). - * Currently the select of connection flags is limited to `STREAM_CLIENT_CONNECT` (default), `STREAM_CLIENT_ASYNC_CONNECT` and `STREAM_CLIENT_PERSISTENT`. - * @see http://php.net/manual/en/function.stream-socket-client.php - * @since 2.0.5 - */ - public $socketClientFlags = STREAM_CLIENT_CONNECT; /** * @var array List of available redis commands http://redis.io/commands */ @@ -236,9 +229,9 @@ class Connection extends Component ]; /** - * @var resource redis socket connection + * @var \Redis resource redis socket connection */ - private $_socket = false; + private $_client = false; /** @@ -257,7 +250,7 @@ public function __sleep() */ public function getIsActive() { - return $this->_socket !== false; + return $this->_client !== false; } /** @@ -267,31 +260,37 @@ public function getIsActive() */ public function open() { - if ($this->_socket !== false) { + if ($this->_client !== false) { return; } $connection = ($this->unixSocket ?: $this->hostname . ':' . $this->port) . ', database=' . $this->database; \Yii::trace('Opening redis DB connection: ' . $connection, __METHOD__); - $this->_socket = @stream_socket_client( - $this->unixSocket ? 'unix://' . $this->unixSocket : 'tcp://' . $this->hostname . ':' . $this->port, - $errorNumber, - $errorDescription, - $this->connectionTimeout ? $this->connectionTimeout : ini_get('default_socket_timeout'), - $this->socketClientFlags - ); - if ($this->_socket) { - if ($this->dataTimeout !== null) { - stream_set_timeout($this->_socket, $timeout = (int) $this->dataTimeout, (int) (($this->dataTimeout - $timeout) * 1000000)); - } + $this->_client = new \Redis; + if ($this->unixSocket) { + $connected = $this->_client->connect($this->unixSocket); + } else { + $connected = $this->_client->connect($this->hostname, $this->port, $this->connectionTimeout, null, 1000); + } + + if ($connected) { if ($this->password !== null) { $this->executeCommand('AUTH', [$this->password]); } $this->executeCommand('SELECT', [$this->database]); $this->initConnection(); } else { - \Yii::error("Failed to open redis DB connection ($connection): $errorNumber - $errorDescription", __CLASS__); - $message = YII_DEBUG ? "Failed to open redis DB connection ($connection): $errorNumber - $errorDescription" : 'Failed to open DB connection.'; - throw new Exception($message, $errorDescription, $errorNumber); + $message = [ + 'Failed to open redis DB connection', + ' (' . $connection . '): ' . $this->_client->getLastError(), + ]; + + \Yii::error(implode('', $message), __CLASS__); + + if (!YII_DEBUG) { + $message[1] .= '.'; + } + + throw new Exception(implode('', $message), $this->_client->getLastError()); } } @@ -301,12 +300,11 @@ public function open() */ public function close() { - if ($this->_socket !== false) { + if ($this->_client !== false) { $connection = ($this->unixSocket ?: $this->hostname . ':' . $this->port) . ', database=' . $this->database; \Yii::trace('Closing DB connection: ' . $connection, __METHOD__); - $this->executeCommand('QUIT'); - stream_socket_shutdown($this->_socket, STREAM_SHUT_RDWR); - $this->_socket = null; + $this->_client->close(); + $this->_client = null; } } @@ -381,79 +379,22 @@ public function __call($name, $params) public function executeCommand($name, $params = []) { $this->open(); + $token = 'Command: ' . $name . PHP_EOL . 'Params: ' . var_export($params, true); - array_unshift($params, $name); - $command = '*' . count($params) . "\r\n"; - foreach ($params as $arg) { - $command .= '$' . mb_strlen($arg, '8bit') . "\r\n" . $arg . "\r\n"; - } - - $token = implode("\n", $params); \Yii::beginProfile($token, 'yii\db\Command::query'); - fwrite($this->_socket, $command); - - $response = $this->parseResponse(implode(' ', $params)); + $response = call_user_func_array([$this->_client, $name], $params); \Yii::endProfile($token, 'yii\db\Command::query'); + return $response; } - /** - * @param string $command - * @return mixed - * @throws Exception on error - */ - public function parseResponse($command) + public function getError() { - if (($line = $this->read()) === false) { - throw new Exception("Failed to read from socket.\nRedis command was: " . $command); - } - $type = $line[0]; - $line = mb_substr($line, 1, -2, '8bit'); - switch ($type) { - case '+': // Status reply - if ($line === 'OK' || $line === 'PONG') { - return true; - } else { - return $line; - } - case '-': // Error reply - throw new Exception("Redis error: " . $line . "\nRedis command was: " . $command); - case ':': // Integer reply - // no cast to int as it is in the range of a signed 64 bit integer - return $line; - case '$': // Bulk replies - if ($line == '-1') { - return null; - } - $length = $line + 2; - $data = ''; - while ($length > 0) { - if (($block = $this->read($length)) === false) { - throw new Exception("Failed to read from socket.\nRedis command was: " . $command); - } - $data .= $block; - $length -= mb_strlen($block, '8bit'); - } - - return mb_substr($data, 0, -2, '8bit'); - case '*': // Multi-bulk replies - $count = (int) $line; - $data = []; - for ($i = 0; $i < $count; $i++) { - $data[] = $this->parseResponse($command); - } - - return $data; - default: - throw new Exception('Received illegal data from redis: ' . $line . "\nRedis command was: " . $command); - } + return $this->_client->getLastError(); } - private function read($length = null) { - if($length) { - return fread($this->_socket, $length); - } - - return fgets($this->_socket); + public function getClient() + { + return $this->_client; } } diff --git a/Session.php b/Session.php index 0ed3a30f0..9617a6168 100644 --- a/Session.php +++ b/Session.php @@ -128,7 +128,7 @@ public function readSession($id) */ public function writeSession($id, $data) { - return (bool) $this->redis->executeCommand('SET', [$this->calculateKey($id), $data, 'EX', $this->getTimeout()]); + return (bool)$this->redis->executeCommand('SETEX', [$this->calculateKey($id), $this->getTimeout(), $data]); } /** diff --git a/tests/RedisConnectionTest.php b/tests/RedisConnectionTest.php index e54fddce0..dedda956c 100644 --- a/tests/RedisConnectionTest.php +++ b/tests/RedisConnectionTest.php @@ -15,7 +15,7 @@ public function testConnect() $db = $this->getConnection(false); $database = $db->database; $db->open(); - $this->assertTrue($db->ping()); + $this->assertEquals('+PONG', $db->ping()); $db->set('YIITESTKEY', 'YIITESTVALUE'); $db->close(); @@ -28,7 +28,7 @@ public function testConnect() $db = $this->getConnection(false); $db->database = 1; $db->open(); - $this->assertNull($db->get('YIITESTKEY')); + $this->assertFalse($db->get('YIITESTKEY')); $db->close(); } @@ -62,7 +62,7 @@ public function testReturnType() { $redis = $this->getConnection(); $redis->executeCommand('SET',['key1','val1']); - $redis->executeCommand('HMSET',['hash1','hk3','hv3','hk4','hv4']); + $redis->executeCommand('HMSET', ['hash1', ['hk3' => 'hv3', 'hk4' => 'hv4']]); $redis->executeCommand('RPUSH',['newlist2','tgtgt','tgtt','44',11]); $redis->executeCommand('SADD',['newset2','segtggttval','sv1','sv2','sv3']); $redis->executeCommand('ZADD',['newz2',2,'ss',3,'pfpf']); @@ -70,11 +70,11 @@ public function testReturnType() sort($allKeys); $this->assertEquals(['hash1', 'key1', 'newlist2', 'newset2', 'newz2'], $allKeys); $expected = [ - 'hash1' => 'hash', - 'key1' => 'string', - 'newlist2' => 'list', - 'newset2' => 'set', - 'newz2' => 'zset', + 'hash1' => \Redis::REDIS_HASH, + 'key1' => \Redis::REDIS_STRING, + 'newlist2' => \Redis::REDIS_LIST, + 'newset2' => \Redis::REDIS_SET, + 'newz2' => \Redis::REDIS_ZSET, ]; foreach($allKeys as $key) { $this->assertEquals($expected[$key], $redis->executeCommand('TYPE',[$key])); diff --git a/tests/data/ar/Customer.php b/tests/data/ar/Customer.php index 1a0678c40..775be5d87 100644 --- a/tests/data/ar/Customer.php +++ b/tests/data/ar/Customer.php @@ -35,6 +35,11 @@ public function getExpensiveOrders() return $this->hasMany(Order::className(), ['customer_id' => 'id'])->andWhere("tonumber(redis.call('HGET','order' .. ':a:' .. pk, 'total')) > 50"); } + public function getOrdersWithItems() + { + return $this->hasMany(Order::className(), ['customer_id' => 'id'])->with('orderItems'); + } + /** * @return \yii\redis\ActiveQuery */ From e79be10f993229b8426d84af2bb10092433618c6 Mon Sep 17 00:00:00 2001 From: Andrey Kolobov Date: Thu, 7 Apr 2016 21:27:38 +0500 Subject: [PATCH 34/36] sudo true for travis --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3cf8224f8..f29885ed9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,6 @@ php: services: - redis-server -# faster builds on new travis setup not using sudo -sudo: false - # cache vendor dirs cache: directories: From 865586b5b8a1e24c1a21995aa55aa332e5eef12f Mon Sep 17 00:00:00 2001 From: Andrey Kolobov Date: Thu, 7 Apr 2016 21:52:47 +0500 Subject: [PATCH 35/36] fix phpredis for php7 --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index f29885ed9..150de8ef8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,11 @@ php: - 7.0 - hhvm +matrix: + allow_failures: + - php: hhvm + - php: 7.0 + services: - redis-server From 70d2ff0a00a33b51ff2ce405c5b0c5f077aa5615 Mon Sep 17 00:00:00 2001 From: Andrey Kolobov Date: Thu, 7 Apr 2016 22:46:27 +0500 Subject: [PATCH 36/36] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 506396b4e..b0fcfac0a 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ yii2-redis module with various fixes and speedups * [fix populate null attributes](https://github.com/E96/yii2-redis/commit/02c879b865937b39f47fb0664329310dcaf3ff94) * [fix integer values in buildKey](https://github.com/E96/yii2-redis/commit/da6ed85ed15bd33b4137083403c027a15b9fc03d) * [Make Connection::parseResponse public](https://github.com/E96/yii2-redis/commit/f5ce8325303cda6bd1bc1ecb62d310a5b01661e4) +* [change connection from socket to phpredis](https://github.com/E96/yii2-redis/commit/d28911a005a02cd3b01940bb8e959813599b287a) Migration guide ===============