mirror of
https://github.com/predis/predis.git
synced 2026-08-18 09:42:27 +00:00
Compare commits
368 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| deee2b6d60 | |||
| bb8cce7bcf | |||
| dc14604f3e | |||
| b000013f22 | |||
| d6da14daa8 | |||
| acb2460f4c | |||
| 213f00042f | |||
| ab0c46332c | |||
| ed19ec3483 | |||
| 90496e76b5 | |||
| 4231c35e09 | |||
| a2fb02d738 | |||
| ca1f398f7c | |||
| 5e07be785a | |||
| b3cd02e2ba | |||
| c50c3393bb | |||
| 4aa3014bb0 | |||
| 92adf32e88 | |||
| c4560304cf | |||
| cf5c118a07 | |||
| bb9a670c83 | |||
| 3e56e880e8 | |||
| 1c71a4e36e | |||
| 5004f5d6fc | |||
| e616f85679 | |||
| 9cd093be24 | |||
| 305d167b08 | |||
| 3271e1edcb | |||
| b240daa106 | |||
| 8fee6ce8c3 | |||
| 35dd44b222 | |||
| 545177f09f | |||
| 2f9337cb9b | |||
| 437d80a7a3 | |||
| 3a14a39d92 | |||
| 5c9457cc2e | |||
| c551fc21f9 | |||
| 0d84606723 | |||
| c021e380d6 | |||
| 5f4b87080f | |||
| 5ae4ac6b49 | |||
| 521ac8f0eb | |||
| fbbef2a0a2 | |||
| 9930e933c6 | |||
| 16957f3b39 | |||
| 9e5371f5ce | |||
| 8ca99f91e4 | |||
| c778843b0d | |||
| dca201291c | |||
| 2e76410e65 | |||
| ca468b785c | |||
| 4a7fb55058 | |||
| fdf663ebba | |||
| 880ad09cad | |||
| 5eccc65d42 | |||
| f225c55a01 | |||
| 8be2418f01 | |||
| b9ebe8a376 | |||
| e2d26926d2 | |||
| 309248042f | |||
| 87452e62d0 | |||
| 31baa9b241 | |||
| 6f942400a1 | |||
| 5e220a0b57 | |||
| 0eb2633348 | |||
| cbbd6bba88 | |||
| 3702f24efc | |||
| 82fefe057b | |||
| 42336537dc | |||
| 802abac55e | |||
| 61e75816ce | |||
| 17f0c08cb6 | |||
| 2b8af1eef2 | |||
| c5f2b441b4 | |||
| 2440a61cba | |||
| 7100884201 | |||
| 2a932d7292 | |||
| 0a6306b73e | |||
| 4363345f7c | |||
| 2ce537d75e | |||
| 7489690306 | |||
| 7376902b20 | |||
| a6bd25412e | |||
| 60cc950a58 | |||
| db82dd9f23 | |||
| 1bc08d9bcc | |||
| 11e4bb44d0 | |||
| cddb849812 | |||
| f2298dd186 | |||
| bceda1d8e6 | |||
| 9f87c849c5 | |||
| 1382146b03 | |||
| cbc08aa5e7 | |||
| de9cd905bb | |||
| 6dd55d7f96 | |||
| 82eb18c6c3 | |||
| ac6b813ba9 | |||
| 6482956d96 | |||
| cf15dd9857 | |||
| 597c61a098 | |||
| 9aa99349b1 | |||
| b6f60f0d72 | |||
| 10235d62dc | |||
| ec2b1eacd2 | |||
| 9c3605ab33 | |||
| 55e6094954 | |||
| 15314b726b | |||
| 292604edbf | |||
| fc8f9f5604 | |||
| 77132e6c6b | |||
| a7571ef0c7 | |||
| 4901408b08 | |||
| dd3897b755 | |||
| 6e7dbe05fb | |||
| f0f9d68a8e | |||
| bb6f1ee0e3 | |||
| ffcc4bba8c | |||
| 83359dff9a | |||
| 710b4f901b | |||
| f3e46683b9 | |||
| 945e05819b | |||
| a64b7354e1 | |||
| 39ff616e86 | |||
| 738ec0c50f | |||
| 1828222e27 | |||
| 111d100ee3 | |||
| 893215a1d4 | |||
| f5d8b9fe2d | |||
| 722b513cea | |||
| 62774c6cc5 | |||
| 8aa2ded5b0 | |||
| 795c3e41b0 | |||
| 59e616b124 | |||
| 157f658f0b | |||
| 343afd312a | |||
| d77b77bbd9 | |||
| 34b678192f | |||
| 4de246cfee | |||
| 6fd6933580 | |||
| c7b38abe71 | |||
| 574ef78f86 | |||
| 1ebabaf8f8 | |||
| 98ec0cc27e | |||
| caf8a46cbb | |||
| 944a16d7c0 | |||
| d1290dfde0 | |||
| 9489d9e5aa | |||
| 94ccb2cc3b | |||
| 6c848db2a0 | |||
| 6ab10b2b70 | |||
| 2d4377fc81 | |||
| f0210e3888 | |||
| 5e88200ed6 | |||
| aed1a7bdf1 | |||
| 2290042680 | |||
| 295e9175ad | |||
| d92f31dc66 | |||
| 8437fbc84f | |||
| 4d58928efd | |||
| a523cf7731 | |||
| 1ad0effb0a | |||
| 0607d84d0c | |||
| a1ee7b68ef | |||
| 0e17edbefb | |||
| 81c0a8f051 | |||
| 1065edc8d1 | |||
| 843ad23ea7 | |||
| e386f5c732 | |||
| a06063d2e6 | |||
| d58929e5a5 | |||
| ecab7e4642 | |||
| a22fc17800 | |||
| 7a50b02c36 | |||
| f6bf2b5977 | |||
| 5850029f89 | |||
| f64bd83f9d | |||
| 922e56b480 | |||
| 5a0dfc3602 | |||
| 39a6e18d71 | |||
| a19de6356c | |||
| 2d01a27e17 | |||
| ad7b8b08cb | |||
| 0ebfc0e7d2 | |||
| 9303029c13 | |||
| 0477499418 | |||
| 9398a793a5 | |||
| 0dff761a61 | |||
| 02ed5a2f4e | |||
| 51932d82e8 | |||
| 00000fde4e | |||
| aeb9b7ccae | |||
| 4273a2a8b6 | |||
| b2284d015f | |||
| c4e0044269 | |||
| 0b6b3b2558 | |||
| 7ef9619f5c | |||
| 3362e474b6 | |||
| 7b3f6e1db5 | |||
| 1536b2aa82 | |||
| 1ab65da368 | |||
| b11fb84282 | |||
| da009e59dd | |||
| 763acd232d | |||
| 75a8253ee4 | |||
| 9368d98ac3 | |||
| 8f514fe893 | |||
| 6964f060b3 | |||
| c125c218ae | |||
| 1f3a010681 | |||
| 49f6b46942 | |||
| c1795de1f3 | |||
| 528cd090d8 | |||
| 5b3a5bbef9 | |||
| 349a70a08a | |||
| c1de65c4ee | |||
| ecbdaa1951 | |||
| 05209e6e7d | |||
| 803a5cfd5b | |||
| faaf853cbe | |||
| 257791edcf | |||
| d0cc7a5947 | |||
| 5adafb352c | |||
| d6d307696a | |||
| f3999660fe | |||
| 18e846c2ad | |||
| 7e4800010a | |||
| 6b5181b030 | |||
| 01483234c7 | |||
| cdadb796ad | |||
| 354e5e26da | |||
| d55826f35c | |||
| 26d7147646 | |||
| 973e8592e3 | |||
| f696ed125e | |||
| 9f6759ca1c | |||
| 89a1e236ce | |||
| 97dfba1e98 | |||
| be8ac3e205 | |||
| a933a13087 | |||
| ce3d42b9cf | |||
| 629329ac76 | |||
| a95860ce00 | |||
| 51e8d6c46e | |||
| 126998631b | |||
| d7f3b8c9d2 | |||
| c9366212d0 | |||
| 5b76b41fda | |||
| b491dff126 | |||
| 774b4014d9 | |||
| 00c5d7de19 | |||
| e3412c4a1b | |||
| 44ebf5a5e4 | |||
| 0c99f9ef28 | |||
| 6e0743a29a | |||
| b047e8b6a1 | |||
| 7be83a1fd6 | |||
| 367ed2c11c | |||
| f0b3014cb4 | |||
| a816adf6e7 | |||
| 7cb20f5a0c | |||
| 62c547601c | |||
| f8b3f18abf | |||
| 0ec9f3351f | |||
| 622e6c6ba2 | |||
| bc212ad2b0 | |||
| e896d89fa8 | |||
| e851aaa21d | |||
| 7664f1f29b | |||
| 104e42cfe0 | |||
| b6a14cda04 | |||
| e61cb4e4f2 | |||
| 1349666494 | |||
| a0487ec5f4 | |||
| 57a7d5d3e6 | |||
| 8235228acd | |||
| 3ceaa39a3c | |||
| 0baad16064 | |||
| 939c0821dd | |||
| eb154cd43d | |||
| d8da74adac | |||
| fda293b573 | |||
| 24fb72a732 | |||
| 8d15503d6c | |||
| 587fbbc446 | |||
| 370d4e72c2 | |||
| 6bc1a38123 | |||
| f7d7cd59c4 | |||
| d46de81d91 | |||
| f4b6c578be | |||
| 2fc0e56a09 | |||
| 8106c8b00a | |||
| b8bfd1405d | |||
| a7ee80702c | |||
| 0eaa1d929d | |||
| a26390915d | |||
| 24c0f846c7 | |||
| f43433baf1 | |||
| 3dfe62a5b5 | |||
| ebb72377bb | |||
| cb91ad1aee | |||
| 5172555009 | |||
| 4dea992cd2 | |||
| 80af1af459 | |||
| abf2ce0bd1 | |||
| c7cae66a97 | |||
| 4f30ac6370 | |||
| 1c8eb7ff6b | |||
| cb09a7a2b5 | |||
| d69d6c726d | |||
| 2b0c8fbb26 | |||
| 55aab86800 | |||
| 6cce9eb35c | |||
| 8277afc7a8 | |||
| b012af3247 | |||
| 7fa3c55f51 | |||
| 73c9b9d5be | |||
| 59798e1f9e | |||
| d0012e67ff | |||
| 65727ca07d | |||
| 4ac1a81aa4 | |||
| 8dd9893a2f | |||
| 35e97967fd | |||
| 7282ca2b52 | |||
| c436e01353 | |||
| df2e9f4e71 | |||
| 6590c44a27 | |||
| bb89cf67e2 | |||
| 7c1d324f30 | |||
| bb6287f22d | |||
| f315404649 | |||
| 8c76bd6761 | |||
| 38fafb22ba | |||
| 5ce683be09 | |||
| e531d39f53 | |||
| fda9f022dd | |||
| 44e92d8a2f | |||
| e75b69f6fd | |||
| 082c51146a | |||
| b02e3f4911 | |||
| 87921f7a05 | |||
| 3fdfc50683 | |||
| ae26ecc8bf | |||
| 231a3440f7 | |||
| ab20c52115 | |||
| 2eaf3d8595 | |||
| bb909c573d | |||
| 35f135be30 | |||
| 474f3ddbe7 | |||
| ae054fc7e1 | |||
| 8168def08f | |||
| 15f3b6030c | |||
| c0d1a74447 | |||
| 6882d08373 | |||
| 871d526300 | |||
| d84bca131b | |||
| 5cd4f41424 | |||
| b3bcf466f5 | |||
| 24d8f68e7f | |||
| 0a8754f9b6 | |||
| 614049cd12 | |||
| 5911145d9f | |||
| 8029faf72a | |||
| e2c08cfe88 | |||
| 3b31b91ad8 | |||
| 7a984e7b76 | |||
| 33e6ee2e48 | |||
| c577c20481 | |||
| 6fbe2d5fa3 |
@@ -0,0 +1,17 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.php]
|
||||
trim_trailing_whitespace = true
|
||||
max_line_length = 120
|
||||
|
||||
[*.{md,yml}]
|
||||
indent_size = 2
|
||||
+8
-1
@@ -1,8 +1,15 @@
|
||||
* text=auto
|
||||
|
||||
/tests export-ignore
|
||||
/tests/PHPUnit export-ignore
|
||||
/tests/Predis export-ignore
|
||||
/tests/bootstrap.php export-ignore
|
||||
/.github export-ignore
|
||||
/.editorconfig export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.php_cs.dist export-ignore
|
||||
/.travis.yml export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
/phpunit.xml.travisci export-ignore
|
||||
/CHANGELOG.md export-ignore
|
||||
/CONTRIBUTING.md export-ignore
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
github: tillkruss
|
||||
custom: "https://www.paypal.me/tillkruss"
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Run command '...'
|
||||
2. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Versions (please complete the following information):**
|
||||
- Predis: [e.g. 1.1.2]
|
||||
- PHP [e.g. 8.0.0]
|
||||
- Redis Server [e.g. 6.0.0]
|
||||
- OS [e.g. Ubuntu 20.10]
|
||||
|
||||
**Code sample**
|
||||
If applicable, a small snippet of code that reproduces the issue.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -1,5 +1,8 @@
|
||||
*.tgz
|
||||
*.phar
|
||||
.php-version
|
||||
.php_cs.cache
|
||||
.phpunit.result.cache
|
||||
phpunit.xml
|
||||
package.xml
|
||||
composer.lock
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
$PREDIS_HEADER = <<<EOS
|
||||
This file is part of the Predis package.
|
||||
|
||||
(c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
EOS;
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setUsingCache(true)
|
||||
->setRules(array(
|
||||
'@Symfony' => true,
|
||||
'header_comment' => array(
|
||||
'header' => $PREDIS_HEADER,
|
||||
),
|
||||
'ordered_imports' => true,
|
||||
'phpdoc_order' => true,
|
||||
'binary_operator_spaces' => array(
|
||||
'align_double_arrow' => false,
|
||||
'align_equals' => false,
|
||||
),
|
||||
'array_syntax' => array('syntax' => 'long'),
|
||||
))
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->in(__DIR__.'/bin')
|
||||
->in(__DIR__.'/src')
|
||||
->in(__DIR__.'/tests')
|
||||
->in(__DIR__.'/examples')
|
||||
);
|
||||
+27
-16
@@ -1,25 +1,36 @@
|
||||
language: php
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- hhvm
|
||||
- hhvm-nightly
|
||||
|
||||
branches:
|
||||
except:
|
||||
- v0.5
|
||||
- v0.6
|
||||
- php5.2_backport
|
||||
- documentation
|
||||
services: redis-server
|
||||
- main
|
||||
- v2.0
|
||||
|
||||
before_install:
|
||||
- docker run -d --rm -p 127.0.0.1:6379:6379 redis:3
|
||||
|
||||
before_script:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- composer self-update
|
||||
- composer install --no-interaction --prefer-source --dev
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit -c phpunit.xml.travisci
|
||||
- travis_retry vendor/bin/phpunit -c phpunit.xml.travisci
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: hhvm-nightly
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.3
|
||||
dist: precise
|
||||
services: redis-server
|
||||
before_install: skip
|
||||
- php: 5.4
|
||||
dist: trusty
|
||||
- php: 5.5
|
||||
dist: trusty
|
||||
- php: 5.6
|
||||
- php: 7.0
|
||||
- php: 7.1
|
||||
- php: 7.2
|
||||
- php: 7.3
|
||||
- php: 7.4
|
||||
- php: 8.0
|
||||
|
||||
+276
@@ -1,3 +1,279 @@
|
||||
v1.1.10 (2022-01-05)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: Avoid PHP 8.1 deprecation notices in `Session/Handler`
|
||||
- __FIX__: Fixed "Cannot use object of type Predis\Response\Error as array"
|
||||
error in `Connection/Aggregate/SentinelReplication`
|
||||
|
||||
|
||||
v1.1.9 (2021-10-05)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: Fixed PHP 8.1 compatibility in `StreamConnection`
|
||||
|
||||
|
||||
v1.1.8 (2021-09-29)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: Ensure compatibility with PHP 8.1.
|
||||
|
||||
|
||||
v1.1.7 (2021-04-04)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: with the phpiredis-based connection backends, failed pipelines led to
|
||||
spurious responses returned after reconnecting to Redis because the underlying
|
||||
reader was not properly reset by discarding buffered replies after disconnecting
|
||||
(ISSUE #363).
|
||||
- __FIX__: removed `cweagans/composer-patches` dev dependency and apply patches
|
||||
using `post-update-cmd` script.
|
||||
|
||||
|
||||
v1.1.6 (2020-09-11)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: reverted support for sentinels authentication implemented in v1.1.5
|
||||
as it was bugged (see ISSUE #658), sorry for the trouble. This is now postponed
|
||||
as it requires a more thorough investigation.
|
||||
|
||||
|
||||
v1.1.5 (2020-09-10)
|
||||
================================================================================
|
||||
|
||||
- __FIX__:~~authentication for sentinels is now supported, previously it was not
|
||||
possible to specify a `password` for sentinels as its value was stripped during
|
||||
initialization because sentinels did not support authentication until Redis 5.
|
||||
**Please note** that with the current implementation each sentinel must have
|
||||
its own `password` parameter set in the parameters list despite this password is
|
||||
the same for all sentinels (read how `requirepass` works on the Redis docs). In
|
||||
this case you should avoid using the global `parameters` client option used to
|
||||
set default parameters for every connection created by Predis as this would end
|
||||
up using the same password even when connecting to actual Redis nodes.~~
|
||||
|
||||
- __FIX__: the username is now correctly retrieved from the userinfo fragment of
|
||||
the URI when using the "redis" scheme and a "username:password" pair is present.
|
||||
Values retrieved from the userinfo fragment always override the ones specified
|
||||
in `username` and `password` if those fields are present in the query string.
|
||||
|
||||
- __FIX__: `Predis\Connection\WebdisConnection` was unable to connect to Webdis
|
||||
when using an IPv4 address in the URL and this is probably due to some change in
|
||||
cURL internals since the last time we tested it.
|
||||
|
||||
- __FIX__: an exception is thrown whe passing `FALSE` or any value evaluating to
|
||||
`FALSE` to the `replication` client option. This was supposed to be unsupported,
|
||||
in fact it actually breaks client initialization and raises a PHP warning. Now
|
||||
the user is alerted with an `InvalidArgumentException` and a proper message.
|
||||
(PR #381).
|
||||
|
||||
|
||||
v1.1.4 (2020-08-31)
|
||||
================================================================================
|
||||
|
||||
- Improved @method annotations for methods responding to Redis commands defined
|
||||
by `Predis\ClientInterface` and `Predis\ClientContextInterface`. (PR #456 and
|
||||
PR #497, other fixes applied after further analysys).
|
||||
|
||||
- __FIX__: the client can now handle ACL authentication when connecting to Redis
|
||||
6.x simply by passing both `username` and `password` to connection parameters.
|
||||
See [the Redis docs](https://redis.io/topics/acl) for details on this topic.
|
||||
|
||||
- __FIX__: NULL or zero-length string values passed to `password` and `database`
|
||||
in the connection parameters list do not trigger spurious `AUTH` and `SELECT`
|
||||
commands anymore when connecting to Redis (ISSUE #436).
|
||||
|
||||
- __FIX__: initializing an iteration over a client instance when it is connected
|
||||
to a standalone Redis server will not throw an exception anymore, instead it
|
||||
will return an iterator that will run for just one loop returning a new client
|
||||
instance using the underlying single-node connection (ISSUE #552, PR #556).
|
||||
|
||||
- __FIX__: `Predis\Cluster\Distributor\HashRingaddNodeToRing()` was calculating
|
||||
the hash required for distribution by using `crc32()` directly instead of the
|
||||
method `Predis\Cluster\Hash\HashGeneratorInterface::hash()` implemented by the
|
||||
class itself. This bug fix does not have any impact on existing clusters that
|
||||
use client-side sharding based on this distributor simply because it does not
|
||||
take any external hash generators so distribution is not going to be affected.
|
||||
|
||||
- __FIX__: `SORT` now always trigger a switch to the master node in replication
|
||||
configurations instead of just when the `STORE` modifier is specified, this is
|
||||
because `SORT` is always considered to be a write operation and actually fails
|
||||
with a `-READONLY` error response when executed against a replica node. (ISSUE
|
||||
#554).
|
||||
|
||||
|
||||
v1.1.3 (2020-08-18)
|
||||
================================================================================
|
||||
|
||||
- Ensure compatibility with PHP 8.
|
||||
|
||||
- Moved repository from `github.com/nrk/predis` to `github.com/predis/predis`.
|
||||
|
||||
- __FIX__: Moved `cweagans/composer-patches` dependency to `require-dev`.
|
||||
|
||||
- __FIX__: Include PHPUnit `.patch` files in exports.
|
||||
|
||||
|
||||
v1.1.2 (2020-08-11)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: pure CRC16 implementation failed to calculate the correct hash when
|
||||
the input value passed to the `hash()` method is an integer (PR #450).
|
||||
|
||||
- __FIX__: make PHP iterator abstractions for `ZSCAN` and `HSCAN` working with
|
||||
PHP 7.2 due to a breaking change, namely the removal of `each()` (PR #448).
|
||||
|
||||
|
||||
v1.1.1 (2016-06-16)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: `password` and `database` from the global `parameters` client option
|
||||
were still being applied to sentinels connections making them fail (sentinels
|
||||
do not understand the `AUTH` and `SELECT` commands) (PR #346).
|
||||
|
||||
- __FIX__: when a sentinel instance reports no sentinel for a service, invoking
|
||||
`connect()` on the redis-sentinel connection backend should fall back to the
|
||||
master connection instead of failing (ISSUE #342).
|
||||
|
||||
- __FIX__: the two connection backends based on ext-phpiredis has some kind of
|
||||
issues with the GC and the internal use of closures as reader callbacks that
|
||||
prevented connections going out of scope from being properly collected and the
|
||||
underlying stream or socket resources from being closed and freed. This should
|
||||
not have had any actual effect in real-world scenarios due to the lifecycle of
|
||||
PHP scripts, but we fixed it anyway (ISSUE #345).
|
||||
|
||||
|
||||
v1.1.0 (2016-06-02)
|
||||
================================================================================
|
||||
|
||||
- The default server profile for the client now targets Redis 3.2.
|
||||
|
||||
- Responses to the following commands are not casted into booleans anymore, the
|
||||
original integer value is returned: `SETNX`, `MSETNX`, `SMOVE`, `SISMEMBER`,
|
||||
`HSET`, `HSETNX`, `HEXISTS`, `PFADD`, `EXISTS`, `MOVE`, `PERSIST`, `EXPIRE`,
|
||||
`EXPIREAT`, `RENAMENX`. This change does not have a significant impact unless
|
||||
when using strict comparisons (=== and !==) the returned value.
|
||||
|
||||
- Non-boolean string values passed to the `persistent` connection parameter can
|
||||
be used to create different persistent connections. Note that this feature was
|
||||
already present in Predis but required both `persistent` and `path` to be set
|
||||
as illustrated by [#139](https://github.com/nrk/predis/pull/139). This change
|
||||
is needed to prevent confusion with how `path` is used to select a database
|
||||
when using the `redis` scheme.
|
||||
|
||||
- The client throws exceptions when Redis returns any kind of error response to
|
||||
initialization commands (the ones being automatically sent when a connection
|
||||
is established, such as `SELECT` and `AUTH` when database and password are set
|
||||
in connection parameters) regardless of the value of the exception option.
|
||||
|
||||
- Using `unix:///path/to/socket` in URI strings to specify a UNIX domain socket
|
||||
file is now deprecated in favor of the format `unix:/path/to/socket` (note the
|
||||
lack of the double slash after the scheme) and will not be supported starting
|
||||
with the next major release.
|
||||
|
||||
- Implemented full support for redis-sentinel.
|
||||
|
||||
- Implemented the ability to specify default connection parameters for aggregate
|
||||
connections with the new `parameters` client option. These parameters augment
|
||||
the usual user-supplied connection parameters (but do not take the precedence
|
||||
over them) when creating new connections and they are mostly useful when the
|
||||
client is using aggregate connections such as redis-cluster and redis-sentinel
|
||||
as these backends can create new connections on the fly based on responses and
|
||||
redirections from Redis.
|
||||
|
||||
- Redis servers protected by SSL-encrypted connections can be accessed by using
|
||||
the `tls` or `rediss` scheme in connection parameters along with SSL-specific
|
||||
options in the `ssl` parameter (see http://php.net/manual/context.ssl.php).
|
||||
|
||||
- `Predis\Client` implements `IteratorAggregate` making it possible to iterate
|
||||
over traversable aggregate connections and get a new client instance for each
|
||||
Redis node.
|
||||
|
||||
- Iterating over an instance of `Predis\Connection\Aggregate\RedisCluster` will
|
||||
return all the connections mapped in the slots map instead of just the ones in
|
||||
the pool. This change makes it possible, when the slots map is retrieved from
|
||||
Redis, to iterate over all of the master nodes in the cluster. When the use of
|
||||
`CLUSTER SLOTS` is disabled via the `useClusterSlots()` method, the iteration
|
||||
returns only the connections with slots ranges associated in their parameters
|
||||
or the ones initialized by `-MOVED` responses in order to make the behaviour
|
||||
of the iteration consistent between the two modes of operation.
|
||||
|
||||
- Various improvements to `Predis\Connection\Aggregate\MasterSlaveReplication`
|
||||
(the "basic" replication backend, not the new one based on redis-sentinel):
|
||||
|
||||
- When the client is not able to send a read-only command to a slave because
|
||||
the current connection fails or the slave is resyncing (`-LOADING` response
|
||||
returned by Redis), the backend discards the failed connection and performs
|
||||
a new attempt on the next slave. When no other slave is available the master
|
||||
server is used for read-only commands as last resort.
|
||||
|
||||
- It is possible to discover the current replication configuration on the fly
|
||||
by invoking the `discover()` method which internally relies on the output of
|
||||
the command `INFO REPLICATION` executed against the master server or one of
|
||||
the slaves. The backend can also be configured to do this automatically when
|
||||
it fails to reach one of the servers.
|
||||
|
||||
- Implemented the `switchToMaster()` and `switchToSlave()` methods to make it
|
||||
easier to force a switch to the master server or a random slave when needed.
|
||||
|
||||
|
||||
v1.0.4 (2016-05-30)
|
||||
================================================================================
|
||||
|
||||
- Added new profile for Redis 3.2 with its new commands: `HSTRLEN`, `BITFIELD`,
|
||||
`GEOADD`, `GEOHASH`, `GEOPOS`, `GEODIST`, `GEORADIUS`, `GEORADIUSBYMEMBER`.
|
||||
The default server profile for Predis is still the one for Redis 3.0 you must
|
||||
set the `profile` client option to `3.2` when initializing the client in order
|
||||
to be able to use them when connecting to Redis 3.2.
|
||||
|
||||
- Various improvements in the handling of redis-cluster:
|
||||
|
||||
- If the connection to a specific node fails when executing a command, the
|
||||
client tries to connect to another node in order to refresh the slots map
|
||||
and perform a new attempt to execute the command.
|
||||
|
||||
- Connections to nodes can be preassigned to non-contiguous slot ranges via
|
||||
the `slots` parameter using a comma separator. This is how it looks like
|
||||
in practice: `tcp://127.0.0.1:6379?slots=0-5460,5500-5600,11000`.
|
||||
|
||||
- __FIX__: broken values returned by `Predis\Collection\Iterator\HashKey` when
|
||||
iterating hash keys containing integer fields (PR #330, ISSUE #331).
|
||||
|
||||
- __FIX__: prevent failures when `Predis\Connection\StreamConnection` serializes
|
||||
commands with holes in their arguments (e.g. `[0 => 'key:0', 2 => 'key:2']`).
|
||||
The same fix has been applied to `Predis\Protocol\Text\RequestSerializer`.
|
||||
(ISSUE #316).
|
||||
|
||||
|
||||
v1.0.3 (2015-07-30)
|
||||
================================================================================
|
||||
|
||||
- __FIX__: the previous release introduced a severe regression on HHVM that made
|
||||
the library unable to connect to Redis when using IPv4 addresses. Code running
|
||||
on the standard PHP interpreter is not affected.
|
||||
|
||||
|
||||
v1.0.2 (2015-07-30)
|
||||
================================================================================
|
||||
|
||||
- IPv6 is now fully supported.
|
||||
|
||||
- Added `redis` as an accepted scheme for connection parameters. When using this
|
||||
scheme, the rules used to parse URI strings match the provisional registration
|
||||
[published by IANA](http://www.iana.org/assignments/uri-schemes/prov/redis).
|
||||
|
||||
- Added new or missing commands: `HSTRLEN` (>= 3.2), `ZREVRANGEBYLEX` (>= 2.8)
|
||||
and `MIGRATE` (>= 2.6).
|
||||
|
||||
- Implemented support for the `ZADD` modifiers `NX|XX`, `CH`, `INCR` (Redis >=
|
||||
3.0.2) using the simplified signature where scores and members are passed as
|
||||
a named array.
|
||||
|
||||
- __FIX__: `Predis\Configuration\Options` must not trigger the autoloader when
|
||||
option values are strings (ISSUE #257).
|
||||
|
||||
- __FIX__: `BITPOS` was not defined in the key-prefix processor (ISSUE #265) and
|
||||
in the replication strategy.
|
||||
|
||||
|
||||
v1.0.1 (2015-01-02)
|
||||
================================================================================
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
## Filing bug reports ##
|
||||
|
||||
Bugs or feature requests can be posted on the [GitHub issues](http://github.com/nrk/predis/issues)
|
||||
Bugs or feature requests can be posted on the [GitHub issues](http://github.com/predis/predis/issues)
|
||||
section of the project.
|
||||
|
||||
When reporting bugs, in addition to the obvious description of your issue you __must__ always provide
|
||||
|
||||
@@ -18,6 +18,14 @@ least to some degree).
|
||||
Yes. Obviously persistent connections actually work only when using PHP configured as a persistent
|
||||
process reused by the web server (see [PHP-FPM](http://php-fpm.org)).
|
||||
|
||||
### Does Predis support SSL-encrypted connections? ###
|
||||
|
||||
Yes. Encrypted connections are mostly useful when connecting to Redis instances exposed by various
|
||||
cloud hosting providers without the need to configure an SSL proxy, but you should also take into
|
||||
account the general performances degradation especially during the connect() operation when the TLS
|
||||
handshake must be performed to secure the connection. Persistent SSL-encrypted connections may help
|
||||
in that respect, but they are supported only when running on PHP >= 7.0.0.
|
||||
|
||||
### Does Predis support transparent (de)serialization of values? ###
|
||||
|
||||
No and it will not ever do that by default. The reason behind this decision is that serialization is
|
||||
@@ -25,7 +33,7 @@ usually something that developers prefer to customize depending on their needs a
|
||||
generalized when using Redis because of the many possible access patterns for your data. This does
|
||||
not mean that it is impossible to have such a feature since you can leverage the extensibility of
|
||||
this library to define your own serialization-aware commands. You can find more details about how to
|
||||
do that [on this issue](http://github.com/nrk/predis/issues/29#issuecomment-1202624).
|
||||
do that [on this issue](http://github.com/predis/predis/issues/29#issuecomment-1202624).
|
||||
|
||||
### How can I force Predis to connect to Redis before sending any command? ###
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2015 Daniele Alessandri
|
||||
Copyright (c) 2009-2016 Daniele Alessandri
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
@@ -1,50 +1,44 @@
|
||||
# Predis #
|
||||
|
||||
[](https://packagist.org/packages/predis/predis)
|
||||
[](https://packagist.org/packages/predis/predis)
|
||||
[](https://packagist.org/packages/predis/predis)
|
||||
[](https://travis-ci.org/nrk/predis)
|
||||
[](http://hhvm.h4cc.de/package/predis/predis)
|
||||
[![Software license][ico-license]](LICENSE)
|
||||
[![Latest stable][ico-version-stable]][link-packagist]
|
||||
[![Latest development][ico-version-dev]][link-packagist]
|
||||
[![Monthly installs][ico-downloads-monthly]][link-downloads]
|
||||
[![Build status][ico-travis]][link-travis]
|
||||
|
||||
Predis is a flexible and feature-complete [Redis](http://redis.io) client library for PHP >= 5.3.
|
||||
Flexible and feature-complete [Redis](http://redis.io) client for PHP >= 5.3 and HHVM >= 2.3.0.
|
||||
|
||||
By default Predis does not require any additional C extension, but it can be optionally paired with
|
||||
[phpiredis](https://github.com/nrk/phpiredis) to lower the overhead of serializing and parsing the
|
||||
Redis protocol. An asynchronous implementation of the client, albeit experimental, is also available
|
||||
through [Predis\Async](https://github.com/nrk/predis-async).
|
||||
Predis does not require any additional C extension by default, but it can be optionally paired with
|
||||
[phpiredis](https://github.com/nrk/phpiredis) to lower the overhead of the serialization and parsing
|
||||
of the [Redis RESP Protocol](http://redis.io/topics/protocol).
|
||||
|
||||
Predis can be used with [HHVM](http://www.hhvm.com) >= 2.3.0, but there are no guarantees you will
|
||||
not run into unexpected issues (especially when the JIT compiler is enabled via `Eval.Jit = true`)
|
||||
due to HHVM being still under heavy development, thus unstable and not yet 100% compatible with PHP.
|
||||
|
||||
More details about the project can be found in our [frequently asked questions](FAQ.md) section or
|
||||
on the online [wiki](https://github.com/nrk/predis/wiki).
|
||||
More details about this project can be found on the [frequently asked questions](FAQ.md).
|
||||
|
||||
|
||||
## Main features ##
|
||||
|
||||
- Wide range of Redis versions supported (from __2.0__ to __3.0__ and __unstable__) using profiles.
|
||||
- Cluster of nodes via client-side sharding using consistent hashing or custom distributors.
|
||||
- Smart support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
|
||||
- Support for master-slave replication configurations (write on master, read from slaves).
|
||||
- Transparent key prefixing for all known Redis commands using a customizable prefixing strategy.
|
||||
- Command pipelining (works on both single nodes and aggregate connections).
|
||||
- Abstraction for Redis transactions (Redis >= 2.0) supporting CAS operations (Redis >= 2.2).
|
||||
- Abstraction for Lua scripting (Redis >= 2.6) with automatic switching between `EVALSHA` or `EVAL`.
|
||||
- Support for different versions of Redis (from __2.0__ to __3.2__) using profiles.
|
||||
- Support for clustering using client-side sharding and pluggable keyspace distributors.
|
||||
- Support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
|
||||
- Support for master-slave replication setups and [redis-sentinel](http://redis.io/topics/sentinel).
|
||||
- Transparent key prefixing of keys using a customizable prefix strategy.
|
||||
- Command pipelining on both single nodes and clusters (client-side sharding only).
|
||||
- Abstraction for Redis transactions (Redis >= 2.0) and CAS operations (Redis >= 2.2).
|
||||
- Abstraction for Lua scripting (Redis >= 2.6) and automatic switching between `EVALSHA` or `EVAL`.
|
||||
- Abstraction for `SCAN`, `SSCAN`, `ZSCAN` and `HSCAN` (Redis >= 2.8) based on PHP iterators.
|
||||
- Connections to Redis are established lazily by the client upon the first command.
|
||||
- Support for both TCP/IP and UNIX domain sockets and persistent connections.
|
||||
- Support for [Webdis](http://webd.is) (both `ext-curl` and `ext-phpiredis` are needed).
|
||||
- Connections are established lazily by the client upon the first command and can be persisted.
|
||||
- Connections can be established via TCP/IP (also TLS/SSL-encrypted) or UNIX domain sockets.
|
||||
- Support for [Webdis](http://webd.is) (requires both `ext-curl` and `ext-phpiredis`).
|
||||
- Support for custom connection classes for providing different network or protocol backends.
|
||||
- Flexible system for defining and registering custom sets of supported commands or profiles.
|
||||
- Flexible system for defining custom commands and profiles and override the default ones.
|
||||
|
||||
|
||||
## How to use Predis ##
|
||||
## How to _install_ and use Predis ##
|
||||
|
||||
Predis is available on [Packagist](http://packagist.org/packages/predis/predis) which allows a quick
|
||||
installation using [Composer](http://packagist.org/about-composer). Alternatively, the library can
|
||||
be found on our [own PEAR channel](http://pear.nrk.io) for a more traditional installation via PEAR.
|
||||
Ultimately, archives of each release are [available on GitHub](https://github.com/nrk/predis/tags).
|
||||
This library can be found on [Packagist](http://packagist.org/packages/predis/predis) for an easier
|
||||
management of projects dependencies using [Composer](http://packagist.org/about-composer) or on our
|
||||
[own PEAR channel](http://pear.nrk.io) for a more traditional installation using PEAR. Ultimately,
|
||||
compressed archives of each release are [available on GitHub](https://github.com/predis/predis/releases).
|
||||
|
||||
|
||||
### Loading the library ###
|
||||
@@ -52,7 +46,7 @@ Ultimately, archives of each release are [available on GitHub](https://github.co
|
||||
Predis relies on the autoloading features of PHP to load its files when needed and complies with the
|
||||
[PSR-4 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md).
|
||||
Autoloading is handled automatically when dependencies are managed through Composer, but it is also
|
||||
possible to leverage its own autoloader in projects or scripts not having any autoload facility:
|
||||
possible to leverage its own autoloader in projects or scripts lacking any autoload facility:
|
||||
|
||||
```php
|
||||
// Prepend a base path if Predis is not available in your "include_path".
|
||||
@@ -61,17 +55,15 @@ require 'Predis/Autoloader.php';
|
||||
Predis\Autoloader::register();
|
||||
```
|
||||
|
||||
It is possible to easily create a [phar](http://www.php.net/manual/en/intro.phar.php) archive from
|
||||
the repository just by launching `bin/create-phar`. The generated phar contains a stub defining an
|
||||
autoloader function for Predis, so you just need to require the phar to start using the library.
|
||||
Alternatively it is possible to generate one single PHP file holding every class like older versions
|
||||
of Predis by launching `bin/create-single-file`, but this practice __is not__ encouraged.
|
||||
It is also possible to create a [phar](http://www.php.net/manual/en/intro.phar.php) archive directly
|
||||
from the repository by launching the `bin/create-phar` script. The generated phar already contains a
|
||||
stub defining its own autoloader, so you just need to `require()` it to start using the library.
|
||||
|
||||
|
||||
### Connecting to Redis ###
|
||||
|
||||
When not specifying any connection parameter to create a new client, Predis assumes `127.0.0.1` and
|
||||
`6379` as the default host and port with a connection timeout of 5 seconds:
|
||||
When creating a client instance without passing any connection parameter, Predis assumes `127.0.0.1`
|
||||
and `6379` as default host and port. The default timeout for the `connect()` operation is 5 seconds:
|
||||
|
||||
```php
|
||||
$client = new Predis\Client();
|
||||
@@ -79,22 +71,57 @@ $client->set('foo', 'bar');
|
||||
$value = $client->get('foo');
|
||||
```
|
||||
|
||||
Connection parameters can be supplied either in the form of URI strings or named arrays. While the
|
||||
latter is the preferred way to supply parameters, URI strings can be useful for quick configurations
|
||||
or when parameters are read from a non-structured source:
|
||||
Connection parameters can be supplied either in the form of URI strings or named arrays. The latter
|
||||
is the preferred way to supply parameters, but URI strings can be useful when parameters are read
|
||||
from non-structured or partially-structured sources:
|
||||
|
||||
```php
|
||||
// Named array of connection parameters:
|
||||
// Parameters passed using a named array:
|
||||
$client = new Predis\Client([
|
||||
'scheme' => 'tcp',
|
||||
'host' => '10.0.0.1',
|
||||
'port' => 6379,
|
||||
]);
|
||||
|
||||
// Same set of parameters, but using an URI string:
|
||||
// Same set of parameters, passed using an URI string:
|
||||
$client = new Predis\Client('tcp://10.0.0.1:6379');
|
||||
```
|
||||
|
||||
Password protected servers can be accessed by adding `password` to the parameters set. When ACLs are
|
||||
enabled on Redis >= 6.0, both `username` and `password` are required for user authentication.
|
||||
|
||||
It is also possible to connect to local instances of Redis using UNIX domain sockets, in this case
|
||||
the parameters must use the `unix` scheme and specify a path for the socket file:
|
||||
|
||||
```php
|
||||
$client = new Predis\Client(['scheme' => 'unix', 'path' => '/path/to/redis.sock']);
|
||||
$client = new Predis\Client('unix:/path/to/redis.sock');
|
||||
```
|
||||
|
||||
The client can leverage TLS/SSL encryption to connect to secured remote Redis instances without the
|
||||
need to configure an SSL proxy like stunnel. This can be useful when connecting to nodes running on
|
||||
various cloud hosting providers. Encryption can be enabled with using the `tls` scheme and an array
|
||||
of suitable [options](http://php.net/manual/context.ssl.php) passed via the `ssl` parameter:
|
||||
|
||||
```php
|
||||
// Named array of connection parameters:
|
||||
$client = new Predis\Client([
|
||||
'scheme' => 'tls',
|
||||
'ssl' => ['cafile' => 'private.pem', 'verify_peer' => true],
|
||||
]);
|
||||
|
||||
// Same set of parameters, but using an URI string:
|
||||
$client = new Predis\Client('tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1');
|
||||
```
|
||||
|
||||
The connection schemes [`redis`](http://www.iana.org/assignments/uri-schemes/prov/redis) (alias of
|
||||
`tcp`) and [`rediss`](http://www.iana.org/assignments/uri-schemes/prov/rediss) (alias of `tls`) are
|
||||
also supported, with the difference that URI strings containing these schemes are parsed following
|
||||
the rules described on their respective IANA provisional registration documents.
|
||||
|
||||
The actual list of supported connection parameters can vary depending on each connection backend so
|
||||
it is recommended to refer to their specific documentation or implementation for details.
|
||||
|
||||
When an array of connection parameters is provided, Predis automatically works in cluster mode using
|
||||
client-side sharding. Both named arrays and URI strings can be mixed when providing configurations
|
||||
for each node:
|
||||
@@ -106,68 +133,133 @@ $client = new Predis\Client([
|
||||
]);
|
||||
```
|
||||
|
||||
The actual list of supported connection parameters can vary depending on each connection backend so
|
||||
it is recommended to refer to their specific documentation or implementation for details.
|
||||
See the [aggregate connections](#aggregate-connections) section of this document for more details.
|
||||
|
||||
Connections to Redis are lazy meaning that the client connects to a server only if and when needed.
|
||||
While it is recommended to let the client do its own stuff under the hood, there may be times when
|
||||
it is still desired to have control of when the connection is opened or closed: this can easily be
|
||||
achieved by invoking `$client->connect()` and `$client->disconnect()`. Please note that the effect
|
||||
of these methods on aggregate connections may differ depending on each specific implementation.
|
||||
|
||||
|
||||
### Client configuration ###
|
||||
|
||||
Various aspects of the client can be configured simply by passing options to the second argument of
|
||||
`Predis\Client::__construct()`:
|
||||
Many aspects and behaviors of the client can be configured by passing specific client options to the
|
||||
second argument of `Predis\Client::__construct()`:
|
||||
|
||||
```php
|
||||
$client = new \Predis\Client(
|
||||
$connection_parameters,
|
||||
['profile' => '2.8', 'prefix' => 'sample:']
|
||||
);
|
||||
$client = new Predis\Client($parameters, ['profile' => '2.8', 'prefix' => 'sample:']);
|
||||
```
|
||||
|
||||
Options are managed using a mini DI-alike container and their values
|
||||
are usually lazily initialized only when needed. Predis by default supports the following options:
|
||||
Options are managed using a mini DI-alike container and their values can be lazily initialized only
|
||||
when needed. The client options supported by default in Predis are:
|
||||
|
||||
- `profile`: which profile to use in order to match a specific version of Redis.
|
||||
- `prefix`: a prefix string that is automatically applied to keys found in commands.
|
||||
- `profile`: specifies the profile to use to match a specific version of Redis.
|
||||
- `prefix`: prefix string automatically applied to keys found in commands.
|
||||
- `exceptions`: whether the client should throw or return responses upon Redis errors.
|
||||
- `connections`: connection backends or a connection factory to be used by the client.
|
||||
- `cluster`: which backend to use for clustering (`predis`, `redis` or custom configuration).
|
||||
- `replication`: which backend to use for replication (predis or custom configuration).
|
||||
- `aggregate`: custom connections aggregator (overrides both `cluster` and `replication`).
|
||||
- `connections`: list of connection backends or a connection factory instance.
|
||||
- `cluster`: specifies a cluster backend (`predis`, `redis` or callable object).
|
||||
- `replication`: specifies a replication backend (`TRUE`, `sentinel` or callable object).
|
||||
- `aggregate`: overrides `cluster` and `replication` to provide a custom connections aggregator.
|
||||
- `parameters`: list of default connection parameters for aggregate connections.
|
||||
|
||||
Users can provide custom options with their values or lazy callable initializers that are stored in
|
||||
the options container for later use through the library.
|
||||
Users can also provide custom options with values or callable objects (for lazy initialization) that
|
||||
are stored in the options container for later use through the library.
|
||||
|
||||
|
||||
### Aggregate connections ###
|
||||
|
||||
Predis is able to aggregate multiple connections which is the base for cluster and replication. By
|
||||
default the client implements a cluster of nodes using either client-side sharding (default) or a
|
||||
Redis-backed solution using [redis-cluster](http://redis.io/topics/cluster-tutorial).
|
||||
As for replication, Predis can handle a single-master and multiple-slaves setup by executing read
|
||||
operations on slaves and switching to the master for write operations. The replication behavior is
|
||||
fully configurable.
|
||||
Aggregate connections are the foundation upon which Predis implements clustering and replication and
|
||||
they are used to group multiple connections to single Redis nodes and hide the specific logic needed
|
||||
to handle them properly depending on the context. Aggregate connections usually require an array of
|
||||
connection parameters when creating a new client instance.
|
||||
|
||||
#### Cluster ####
|
||||
|
||||
By default, when no specific client options are set and an array of connection parameters is passed
|
||||
to the client's constructor, Predis configures itself to work in clustering mode using a traditional
|
||||
client-side sharding approach to create a cluster of independent nodes and distribute the keyspace
|
||||
among them. This approach needs some form of external health monitoring of nodes and requires manual
|
||||
operations to rebalance the keyspace when changing its configuration by adding or removing nodes:
|
||||
|
||||
```php
|
||||
$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
|
||||
|
||||
$client = new Predis\Client($parameters);
|
||||
```
|
||||
|
||||
Along with Redis 3.0, a new supervised and coordinated type of clustering was introduced in the form
|
||||
of [redis-cluster](http://redis.io/topics/cluster-tutorial). This kind of approach uses a different
|
||||
algorithm to distribute the keyspaces, with Redis nodes coordinating themselves by communicating via
|
||||
a gossip protocol to handle health status, rebalancing, nodes discovery and request redirection. In
|
||||
order to connect to a cluster managed by redis-cluster, the client requires a list of its nodes (not
|
||||
necessarily complete since it will automatically discover new nodes if necessary) and the `cluster`
|
||||
client options set to `redis`:
|
||||
|
||||
```php
|
||||
$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
|
||||
$options = ['cluster' => 'redis'];
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
```
|
||||
|
||||
#### Replication ####
|
||||
|
||||
The client can be configured to work in a master / slave replication setup by executing read-only
|
||||
commands on slave nodes and automatically switch to the master node as soon as a command performing
|
||||
a write operation is executed. This is the basic configuration needed to work with replication:
|
||||
The client can be configured to operate in a single master / multiple slaves setup to provide better
|
||||
service availability. When using replication, Predis recognizes read-only commands and sends them to
|
||||
a random slave in order to provide some sort of load-balancing and switches to the master as soon as
|
||||
it detects a command that performs any kind of operation that would end up modifying the keyspace or
|
||||
the value of a key. Instead of raising a connection error when a slave fails, the client attempts to
|
||||
fall back to a different slave among the ones provided in the configuration.
|
||||
|
||||
The basic configuration needed to use the client in replication mode requires one Redis server to be
|
||||
identified as the master (this can be done via connection parameters using the `alias` parameter set
|
||||
to `master`) and one or more servers acting as slaves:
|
||||
|
||||
```php
|
||||
// Parameters require one master node specifically marked with `alias=master`.
|
||||
$parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2?alias=slave-01'];
|
||||
$parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
|
||||
$options = ['replication' => true];
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
```
|
||||
|
||||
While Predis is able to distinguish commands performing write and read-only operations, `EVAL` and
|
||||
`EVALSHA` represent a corner case in which the client switches to the master node because it is not
|
||||
able to tell when a Lua script is safe to be executed on slaves. While this is the default behavior,
|
||||
when certain Lua scripts do not perform write operations it is possible to provide an hint to tell
|
||||
the client to stick with slaves for their execution.
|
||||
The above configuration has a static list of servers and relies entirely on the client's logic, but
|
||||
it is possible to rely on [`redis-sentinel`](http://redis.io/topics/sentinel) for a more robust HA
|
||||
environment with sentinel servers acting as a source of authority for clients for service discovery.
|
||||
The minimum configuration required by the client to work with redis-sentinel is a list of connection
|
||||
parameters pointing to a bunch of sentinel instances, the `replication` option set to `sentinel` and
|
||||
the `service` option set to the name of the service:
|
||||
|
||||
```php
|
||||
$parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2?alias=slave-01'];
|
||||
$sentinels = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
|
||||
$options = ['replication' => 'sentinel', 'service' => 'mymaster'];
|
||||
|
||||
$client = new Predis\Client($sentinels, $options);
|
||||
```
|
||||
|
||||
If the master and slave nodes are configured to require an authentication from clients, a password
|
||||
must be provided via the global `parameters` client option. This option can also be used to specify
|
||||
a different database index. The client options array would then look like this:
|
||||
|
||||
```php
|
||||
$options = [
|
||||
'replication' => 'sentinel',
|
||||
'service' => 'mymaster',
|
||||
'parameters' => [
|
||||
'password' => $secretpassword,
|
||||
'database' => 10,
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
While Predis is able to distinguish commands performing write and read-only operations, `EVAL` and
|
||||
`EVALSHA` represent a corner case in which the client switches to the master node because it cannot
|
||||
tell when a Lua script is safe to be executed on slaves. While this is indeed the default behavior,
|
||||
when certain Lua scripts do not perform write operations it is possible to provide an hint to tell
|
||||
the client to stick with slaves for their execution:
|
||||
|
||||
```php
|
||||
$parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
|
||||
$options = ['replication' => function () {
|
||||
// Set scripts that won't trigger a switch from a slave to the master node.
|
||||
$strategy = new Predis\Replication\ReplicationStrategy();
|
||||
@@ -181,29 +273,8 @@ $client->eval($LUA_SCRIPT, 0); // Sticks to slave using `eval`...
|
||||
$client->evalsha(sha1($LUA_SCRIPT), 0); // ... and `evalsha`, too.
|
||||
```
|
||||
|
||||
The `examples` directory contains two complete scripts showing how replication can be configured for
|
||||
[simple](examples/replication_simple.php) or [complex](examples/replication_complex.php) scenarios.
|
||||
|
||||
|
||||
#### Cluster ####
|
||||
|
||||
Simply passing an array of connection parameters to the client constructor configures Predis to work
|
||||
in cluster mode using client-side sharding. If you, on the other hand, want to leverage Redis >= 3.0
|
||||
nodes coordinated by redis-cluster, then the client must be initialized like this:
|
||||
|
||||
```php
|
||||
$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2'];
|
||||
$options = ['cluster' => 'redis'];
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
```
|
||||
|
||||
When using redis-cluster, it is not necessary to pass all of the nodes that compose your cluster but
|
||||
you can simply specify only a few nodes: Predis will automatically fetch the full and updated slots
|
||||
map directly from Redis by contacting one of the servers.
|
||||
|
||||
__NOTE__: our support for redis-cluster does not currently consider master / slave replication but
|
||||
this feature will be added in a future release of this library.
|
||||
The [`examples`](examples/) directory contains a few scripts that demonstrate how the client can be
|
||||
configured and used to leverage replication in both basic and complex scenarios.
|
||||
|
||||
|
||||
### Command pipelines ###
|
||||
@@ -214,7 +285,7 @@ The client can execute the pipeline inside a callable block or return a pipeline
|
||||
ability to chain commands thanks to its fluent interface:
|
||||
|
||||
```php
|
||||
// Executes a pipeline inside a given callable block:
|
||||
// Executes a pipeline inside the given callable block:
|
||||
$responses = $client->pipeline(function ($pipe) {
|
||||
for ($i = 0; $i < 1000; $i++) {
|
||||
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
|
||||
@@ -222,7 +293,7 @@ $responses = $client->pipeline(function ($pipe) {
|
||||
}
|
||||
});
|
||||
|
||||
// Returns a pipeline instance with fluent interface:
|
||||
// Returns a pipeline that can be chained thanks to its fluent interface:
|
||||
$responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute();
|
||||
```
|
||||
|
||||
@@ -233,13 +304,13 @@ The client provides an abstraction for Redis transactions based on `MULTI` and `
|
||||
interface to command pipelines:
|
||||
|
||||
```php
|
||||
// Executes a transaction inside a given callable block:
|
||||
// Executes a transaction inside the given callable block:
|
||||
$responses = $client->transaction(function ($tx) {
|
||||
$tx->set('foo', 'bar');
|
||||
$tx->get('foo');
|
||||
});
|
||||
|
||||
// Returns a transaction instance with fluent interface:
|
||||
// Returns a transaction that can be chained thanks to its fluent interface:
|
||||
$responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute();
|
||||
```
|
||||
|
||||
@@ -251,9 +322,9 @@ of a transaction using CAS you can see [the following example](examples/transact
|
||||
### Adding new commands ###
|
||||
|
||||
While we try to update Predis to stay up to date with all the commands available in Redis, you might
|
||||
prefer to stick with an older version of the library or provide a different way to filter arguments
|
||||
or parse responses for specific commands. To achieve that, Predis provides the ability to implement
|
||||
new command classes to define or override commands in the server profiles used by the client:
|
||||
prefer to stick with an old version of the library or provide a different way to filter arguments or
|
||||
parse responses for specific commands. To achieve that, Predis provides the ability to implement new
|
||||
command classes to define or override commands in the default server profiles used by the client:
|
||||
|
||||
```php
|
||||
// Define a new command by extending Predis\Command\Command:
|
||||
@@ -273,8 +344,8 @@ $response = $client->newcmd();
|
||||
```
|
||||
|
||||
There is also a method to send raw commands without filtering their arguments or parsing responses.
|
||||
Users must provide the arguments list as an array, following the command signatures as defined by
|
||||
the [Redis documentation for commands](http://redis.io/commands):
|
||||
Users must provide the list of arguments for the command as an array, following the signatures as
|
||||
defined by the [Redis documentation for commands](http://redis.io/commands):
|
||||
|
||||
```php
|
||||
$response = $client->executeRaw(['SET', 'foo', 'bar']);
|
||||
@@ -284,16 +355,16 @@ $response = $client->executeRaw(['SET', 'foo', 'bar']);
|
||||
### Script commands ###
|
||||
|
||||
While it is possible to leverage [Lua scripting](http://redis.io/commands/eval) on Redis 2.6+ using
|
||||
[`EVAL`](http://redis.io/commands/eval) and [`EVALSHA`](http://redis.io/commands/evalsha), Predis
|
||||
offers script commands as an higher level abstraction aiming to make things simple. Script commands
|
||||
can be registered in the server profile used by the client and are accessible as if they were plain
|
||||
Redis commands, but they define Lua scripts that get transmitted to the server for remote execution.
|
||||
Internally they use [`EVALSHA`](http://redis.io/commands/evalsha) by default and identify a script
|
||||
by its SHA1 hash to save bandwidth, but [`EVAL`](http://redis.io/commands/eval) is used as a fall
|
||||
back when needed:
|
||||
directly [`EVAL`](http://redis.io/commands/eval) and [`EVALSHA`](http://redis.io/commands/evalsha),
|
||||
Predis offers script commands as an higher level abstraction built upon them to make things simple.
|
||||
Script commands can be registered in the server profile used by the client and are accessible as if
|
||||
they were plain Redis commands, but they define Lua scripts that get transmitted to the server for
|
||||
remote execution. Internally they use [`EVALSHA`](http://redis.io/commands/evalsha) by default and
|
||||
identify a script by its SHA1 hash to save bandwidth, but [`EVAL`](http://redis.io/commands/eval)
|
||||
is used as a fall back when needed:
|
||||
|
||||
```php
|
||||
// Define a new scriptable command by extending Predis\Command\ScriptCommand:
|
||||
// Define a new script command by extending Predis\Command\ScriptCommand:
|
||||
class ListPushRandomValue extends Predis\Command\ScriptCommand
|
||||
{
|
||||
public function getKeysCount()
|
||||
@@ -312,7 +383,7 @@ LUA;
|
||||
}
|
||||
}
|
||||
|
||||
// Inject your script command in the current profile:
|
||||
// Inject the script command in the current profile:
|
||||
$client = new Predis\Client();
|
||||
$client->getProfile()->defineCommand('lpushrand', 'ListPushRandomValue');
|
||||
|
||||
@@ -325,19 +396,19 @@ $response = $client->lpushrand('random_values', $seed = mt_rand());
|
||||
Predis can use different connection backends to connect to Redis. Two of them leverage a third party
|
||||
extension such as [phpiredis](https://github.com/nrk/phpiredis) resulting in major performance gains
|
||||
especially when dealing with big multibulk responses. While one is based on PHP streams, the other
|
||||
is based on socket resources provided by `ext-socket`. Both support TCP/IP or UNIX domain sockets:
|
||||
is based on socket resources provided by `ext-socket`. Both support TCP/IP and UNIX domain sockets:
|
||||
|
||||
```php
|
||||
$client = new Predis\Client('tcp://127.0.0.1', [
|
||||
'connections' => [
|
||||
'tcp' => 'Predis\Connection\PhpiredisStreamConnection', // PHP streams
|
||||
'unix' => 'Predis\Connection\PhpiredisSocketConnection', // ext-socket
|
||||
'tcp' => 'Predis\Connection\PhpiredisStreamConnection', // PHP stream resources
|
||||
'unix' => 'Predis\Connection\PhpiredisSocketConnection', // ext-socket resources
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
Developers can create their own connection classes to support whole new network backends, extend
|
||||
existing ones or provide completely different implementations. Connection classes must implement
|
||||
existing classes or provide completely different implementations. Connection classes must implement
|
||||
`Predis\Connection\NodeConnectionInterface` or extend `Predis\Connection\AbstractConnection`:
|
||||
|
||||
```php
|
||||
@@ -376,14 +447,14 @@ Predis has a comprehensive test suite covering every aspect of the library. This
|
||||
integration tests against a running instance of Redis (>= 2.4.0 is required) to verify the correct
|
||||
behavior of the implementation of each command and automatically skips commands not defined in the
|
||||
specified Redis profile. If you do not have Redis up and running, integration tests can be disabled.
|
||||
By default the test suite is configured to execute integration tests using the profile for Redis 2.8
|
||||
By default the test suite is configured to execute integration tests using the profile for Redis 3.2
|
||||
(which is the current stable version of Redis) but can optionally target a Redis instance built from
|
||||
the `unstable` branch by modifying `phpunit.xml` and setting `REDIS_SERVER_VERSION` to `dev` so that
|
||||
the development server profile will be used. You can refer to [the tests README](tests/README.md)
|
||||
for more detailed information about testing Predis.
|
||||
|
||||
Predis uses Travis CI for continuous integration and the history for past and current builds can be
|
||||
found [on its project page](http://travis-ci.org/nrk/predis).
|
||||
found [on its project page](http://travis-ci.org/predis/predis).
|
||||
|
||||
|
||||
## Other ##
|
||||
@@ -391,9 +462,9 @@ found [on its project page](http://travis-ci.org/nrk/predis).
|
||||
|
||||
### Project related links ###
|
||||
|
||||
- [Source code](https://github.com/nrk/predis)
|
||||
- [Wiki](https://wiki.github.com/nrk/predis)
|
||||
- [Issue tracker](https://github.com/nrk/predis/issues)
|
||||
- [Source code](https://github.com/predis/predis)
|
||||
- [Wiki](https://github.com/predis/predis/wiki)
|
||||
- [Issue tracker](https://github.com/predis/predis/issues)
|
||||
- [PEAR channel](http://pear.nrk.io)
|
||||
|
||||
|
||||
@@ -405,3 +476,14 @@ found [on its project page](http://travis-ci.org/nrk/predis).
|
||||
### License ###
|
||||
|
||||
The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)).
|
||||
|
||||
[ico-license]: https://img.shields.io/github/license/predis/predis.svg?style=flat-square
|
||||
[ico-version-stable]: https://img.shields.io/packagist/v/predis/predis.svg?style=flat-square
|
||||
[ico-version-dev]: https://img.shields.io/packagist/vpre/predis/predis.svg?style=flat-square
|
||||
[ico-downloads-monthly]: https://img.shields.io/packagist/dm/predis/predis.svg?style=flat-square
|
||||
[ico-travis]: https://img.shields.io/travis/predis/predis.svg?style=flat-square
|
||||
[ico-hhvm]: https://img.shields.io/hhvm/predis/predis.svg?style=flat-square
|
||||
|
||||
[link-packagist]: https://packagist.org/packages/predis/predis
|
||||
[link-travis]: https://travis-ci.org/predis/predis
|
||||
[link-downloads]: https://packagist.org/packages/predis/predis/stats
|
||||
|
||||
+2
-2
@@ -115,7 +115,7 @@ function addPackageFile($pkg, $fileinfo, $role, $baseDir = '')
|
||||
function generatePackageXml($packageINI)
|
||||
{
|
||||
$XML = <<<XML
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.4.10" version="2.0"
|
||||
xmlns="http://pear.php.net/dtd/package-2.0"
|
||||
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
|
||||
@@ -197,7 +197,7 @@ function rewritePackageInstallAs($pkg)
|
||||
|
||||
function savePackageXml($xml)
|
||||
{
|
||||
$dom = new DOMDocument("1.0");
|
||||
$dom = new DOMDocument("1.0", "UTF-8");
|
||||
$dom->preserveWhiteSpace = false;
|
||||
$dom->formatOutput = true;
|
||||
$dom->loadXML($xml->asXML());
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ spl_autoload_register(function (\$class) {
|
||||
}
|
||||
}
|
||||
});
|
||||
__HALT_COMPILER();
|
||||
__halt_compiler();
|
||||
EOSTUB;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// files, but namespaces and classes definitions must follow a precise order
|
||||
// when dealing with subclassing and inheritance.
|
||||
//
|
||||
// The current implementation is pretty naïve, but it should do for now.
|
||||
// The current implementation is pretty naïve, but it should do for now.
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
class CommandLine
|
||||
@@ -27,10 +27,10 @@ class CommandLine
|
||||
public static function getOptions()
|
||||
{
|
||||
$parameters = array(
|
||||
's:' => 'source:',
|
||||
'o:' => 'output:',
|
||||
'e:' => 'exclude:',
|
||||
'E:' => 'exclude-classes:',
|
||||
's:' => 'source:',
|
||||
'o:' => 'output:',
|
||||
'e:' => 'exclude:',
|
||||
'E:' => 'exclude-classes:',
|
||||
);
|
||||
|
||||
$getops = getopt(implode(array_keys($parameters)), $parameters);
|
||||
|
||||
+22
-10
@@ -1,36 +1,48 @@
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"type": "library",
|
||||
"description": "Flexible and feature-complete PHP client library for Redis",
|
||||
"description": "Flexible and feature-complete Redis client for PHP and HHVM",
|
||||
"keywords": ["nosql", "redis", "predis"],
|
||||
"homepage": "http://github.com/nrk/predis",
|
||||
"homepage": "http://github.com/predis/predis",
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"issues": "https://github.com/nrk/predis/issues"
|
||||
"issues": "https://github.com/predis/predis/issues"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daniele Alessandri",
|
||||
"email": "suppakilla@gmail.com",
|
||||
"homepage": "http://clorophilla.net"
|
||||
"homepage": "http://clorophilla.net",
|
||||
"role": "Creator & Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Till Krüss",
|
||||
"homepage": "https://till.im",
|
||||
"role": "Maintainer"
|
||||
}
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tillkruss"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
"phpunit/phpunit": "~4.8"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol",
|
||||
"ext-curl": "Allows access to Webdis when paired with phpiredis"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"Predis\\": "src/"}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1-dev"
|
||||
"psr-4": {
|
||||
"Predis\\": "src/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-update-cmd": "@php -f tests/apply-patches.php"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ require __DIR__.'/shared.php';
|
||||
// their own distributors used by the client to distribute keys among a cluster
|
||||
// of servers.
|
||||
|
||||
use Predis\Cluster\PredisStrategy;
|
||||
use Predis\Cluster\Distributor\DistributorInterface;
|
||||
use Predis\Cluster\Hash\HashGeneratorInterface;
|
||||
use Predis\Cluster\PredisStrategy;
|
||||
use Predis\Connection\Aggregate\PredisCluster;
|
||||
|
||||
class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
|
||||
@@ -34,7 +34,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
|
||||
public function add($node, $weight = null)
|
||||
{
|
||||
$this->nodes[] = $node;
|
||||
$this->nodesCount++;
|
||||
++$this->nodesCount;
|
||||
}
|
||||
|
||||
public function remove($node)
|
||||
@@ -99,7 +99,7 @@ $options = array(
|
||||
|
||||
$client = new Predis\Client($multiple_servers, $options);
|
||||
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
for ($i = 0; $i < 100; ++$i) {
|
||||
$client->set("key:$i", str_pad($i, 4, '0', 0));
|
||||
$client->get("key:$i");
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class SimpleDebuggableConnection extends StreamConnection
|
||||
$firtsArg = $command->getArgument(0);
|
||||
$timestamp = round(microtime(true) - $this->tstart, 4);
|
||||
|
||||
$debug = $command->getId();
|
||||
$debug = $command->getId();
|
||||
$debug .= isset($firtsArg) ? " $firtsArg " : ' ';
|
||||
$debug .= "$direction $this";
|
||||
$debug .= " [{$timestamp}s]";
|
||||
|
||||
@@ -26,7 +26,7 @@ var_export($response); echo PHP_EOL;
|
||||
$mkv = array(
|
||||
'uid:0001' => '1st user',
|
||||
'uid:0002' => '2nd user',
|
||||
'uid:0003' => '3rd user'
|
||||
'uid:0003' => '3rd user',
|
||||
);
|
||||
|
||||
$client->mset($mkv);
|
||||
@@ -45,7 +45,7 @@ array (
|
||||
// their arguments are not filtered nor responses coming from Redis are parsed.
|
||||
|
||||
$response = $client->executeRaw(array(
|
||||
'MGET', 'uid:0001', 'uid:0002', 'uid:0003'
|
||||
'MGET', 'uid:0001', 'uid:0002', 'uid:0003',
|
||||
));
|
||||
|
||||
var_export($response); echo PHP_EOL;
|
||||
|
||||
@@ -55,7 +55,7 @@ $client = new Predis\Client($single_server, array(
|
||||
$profile->defineCommand('increxby', 'IncrementExistingKeysBy');
|
||||
|
||||
return $profile;
|
||||
}
|
||||
},
|
||||
));
|
||||
|
||||
$client->mset('foo', 10, 'foobar', 100);
|
||||
|
||||
@@ -28,7 +28,7 @@ foreach (($monitor = $client->monitor()) as $event) {
|
||||
// If we notice a ECHO command with the message QUIT_MONITOR, we stop the
|
||||
// monitor consumer and then break the loop.
|
||||
if ($event->command === 'ECHO' && $event->arguments === '"QUIT_MONITOR"') {
|
||||
echo "Exiting the monitor loop...", PHP_EOL;
|
||||
echo 'Exiting the monitor loop...', PHP_EOL;
|
||||
$monitor->stop();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ foreach ($pubsub as $message) {
|
||||
case 'message':
|
||||
if ($message->channel == 'control_channel') {
|
||||
if ($message->payload == 'quit_loop') {
|
||||
echo "Aborting pubsub loop...", PHP_EOL;
|
||||
echo 'Aborting pubsub loop...', PHP_EOL;
|
||||
$pubsub->unsubscribe();
|
||||
} else {
|
||||
echo "Received an unrecognized command: {$message->payload}.", PHP_EOL;
|
||||
|
||||
@@ -34,7 +34,7 @@ $client = new Predis\Client($single_server, array('profile' => '2.8'));
|
||||
|
||||
// Prepare some keys for our example
|
||||
$client->del('predis:set', 'predis:zset', 'predis:hash');
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
for ($i = 0; $i < 5; ++$i) {
|
||||
$client->sadd('predis:set', "member:$i");
|
||||
$client->zadd('predis:zset', -$i, "member:$i");
|
||||
$client->hset('predis:hash', "field:$i", "value:$i");
|
||||
|
||||
@@ -81,5 +81,5 @@ $hashes = $client->hmgetall('metavars', 'servers');
|
||||
$replication = $client->getConnection();
|
||||
$stillOnSlave = $replication->getCurrent() === $replication->getConnectionById('slave');
|
||||
|
||||
echo "Is still on slave? ", $stillOnSlave ? 'YES!' : 'NO!', PHP_EOL;
|
||||
echo 'Is still on slave? ', $stillOnSlave ? 'YES!' : 'NO!', PHP_EOL;
|
||||
var_export($hashes);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
require __DIR__.'/shared.php';
|
||||
|
||||
// Predis supports redis-sentinel to provide high availability in master / slave
|
||||
// scenarios. The only but relevant difference with a basic replication scenario
|
||||
// is that sentinel servers can manage the master server and its slaves based on
|
||||
// their state, which means that they are able to provide an authoritative and
|
||||
// updated configuration to clients thus avoiding static configurations for the
|
||||
// replication servers and their roles.
|
||||
|
||||
// Instead of connection parameters pointing to redis nodes, we provide a list
|
||||
// of instances of redis-sentinel. Users should always provide a timeout value
|
||||
// low enough to not hinder operations just in case a sentinel is unreachable
|
||||
// but Predis uses a default value of 100 milliseconds for sentinel parameters
|
||||
// without an explicit timeout value.
|
||||
//
|
||||
// NOTE: in real-world scenarios sentinels should be running on different hosts!
|
||||
$sentinels = array(
|
||||
'tcp://127.0.0.1:5380?timeout=0.100',
|
||||
'tcp://127.0.0.1:5381?timeout=0.100',
|
||||
'tcp://127.0.0.1:5382?timeout=0.100',
|
||||
);
|
||||
|
||||
$client = new Predis\Client($sentinels, array(
|
||||
'replication' => 'sentinel',
|
||||
'service' => 'mymaster',
|
||||
));
|
||||
|
||||
// Read operation.
|
||||
$exists = $client->exists('foo') ? 'yes' : 'no';
|
||||
$current = $client->getConnection()->getCurrent()->getParameters();
|
||||
echo "Does 'foo' exist on {$current->alias}? $exists.", PHP_EOL;
|
||||
|
||||
// Write operation.
|
||||
$client->set('foo', 'bar');
|
||||
$current = $client->getConnection()->getCurrent()->getParameters();
|
||||
echo "Now 'foo' has been set to 'bar' on {$current->alias}!", PHP_EOL;
|
||||
|
||||
// Read operation.
|
||||
$bar = $client->get('foo');
|
||||
$current = $client->getConnection()->getCurrent()->getParameters();
|
||||
echo "We fetched 'foo' from {$current->alias} and its value is '$bar'.", PHP_EOL;
|
||||
|
||||
/* OUTPUT:
|
||||
Does 'foo' exist on slave-127.0.0.1:6381? yes.
|
||||
Now 'foo' has been set to 'bar' on master!
|
||||
We fetched 'foo' from master and its value is 'bar'.
|
||||
*/
|
||||
@@ -25,7 +25,7 @@ require __DIR__.'/shared.php';
|
||||
//
|
||||
|
||||
if (!interface_exists('SessionHandlerInterface')) {
|
||||
die("ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 ".
|
||||
die('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 '.
|
||||
"or a polyfill for SessionHandlerInterface provided by an external package.\n");
|
||||
}
|
||||
|
||||
|
||||
+13
-9
@@ -9,6 +9,10 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
die("Example scripts are meant to be executed locally via CLI.");
|
||||
}
|
||||
|
||||
require __DIR__.'/../autoload.php';
|
||||
|
||||
function redis_version($info)
|
||||
@@ -23,22 +27,22 @@ function redis_version($info)
|
||||
}
|
||||
|
||||
$single_server = array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'database' => 15
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'database' => 15,
|
||||
);
|
||||
|
||||
$multiple_servers = array(
|
||||
array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'database' => 15,
|
||||
'alias' => 'first',
|
||||
'alias' => 'first',
|
||||
),
|
||||
array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6380,
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6380,
|
||||
'database' => 15,
|
||||
'alias' => 'second',
|
||||
'alias' => 'second',
|
||||
),
|
||||
);
|
||||
|
||||
@@ -28,7 +28,7 @@ function zpop($client, $key)
|
||||
{
|
||||
$element = null;
|
||||
$options = array(
|
||||
'cas' => true, // Initialize with support for CAS operations
|
||||
'cas' => true, // Initialize with support for CAS operations
|
||||
'watch' => $key, // Key that needs to be WATCHed to detect changes
|
||||
'retry' => 3, // Number of retries on aborted transactions, after
|
||||
// which the client bails out with an exception.
|
||||
@@ -49,4 +49,4 @@ function zpop($client, $key)
|
||||
$client = new Predis\Client($single_server);
|
||||
$zpopped = zpop($client, 'zset');
|
||||
|
||||
echo isset($zpopped) ? "ZPOPed $zpopped" : "Nothing to ZPOP!", PHP_EOL;
|
||||
echo isset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL;
|
||||
|
||||
+2
-2
@@ -7,10 +7,10 @@
|
||||
|
||||
[package]
|
||||
name = "Predis"
|
||||
desc = "Flexible and feature-complete PHP client library for Redis"
|
||||
desc = "Flexible and feature-complete Redis client for PHP and HHVM"
|
||||
homepage = "http://github.com/nrk/predis"
|
||||
license = "MIT"
|
||||
version = "1.1.0"
|
||||
version = "1.1.11"
|
||||
stability = "devel"
|
||||
channel = "pear.nrk.io"
|
||||
|
||||
|
||||
+13
-2
@@ -1,6 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit bootstrap="tests/bootstrap.php" colors="true" strict="true">
|
||||
<phpunit bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="true"
|
||||
beStrictAboutTestSize="true"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true">
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Predis Test Suite">
|
||||
<directory>tests/Predis/</directory>
|
||||
@@ -27,7 +38,7 @@
|
||||
|
||||
<php>
|
||||
<!-- Redis -->
|
||||
<const name="REDIS_SERVER_VERSION" value="2.8" />
|
||||
<const name="REDIS_SERVER_VERSION" value="3.2" />
|
||||
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="15" />
|
||||
|
||||
+13
-6
@@ -1,6 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit bootstrap="tests/bootstrap.php" colors="true" strict="true">
|
||||
<phpunit bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="true"
|
||||
beStrictAboutTestSize="true"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true">
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Predis Test Suite">
|
||||
<directory>tests/Predis/</directory>
|
||||
@@ -25,13 +36,9 @@
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-text" target="php://stdout" />
|
||||
</logging>
|
||||
|
||||
<php>
|
||||
<!-- Redis -->
|
||||
<const name="REDIS_SERVER_VERSION" value="2.8" />
|
||||
<const name="REDIS_SERVER_VERSION" value="3.2" />
|
||||
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="15" />
|
||||
|
||||
+3
-3
@@ -29,7 +29,7 @@ class Autoloader
|
||||
public function __construct($baseDirectory = __DIR__)
|
||||
{
|
||||
$this->directory = $baseDirectory;
|
||||
$this->prefix = __NAMESPACE__ . '\\';
|
||||
$this->prefix = __NAMESPACE__.'\\';
|
||||
$this->prefixLength = strlen($this->prefix);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class Autoloader
|
||||
*/
|
||||
public static function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
|
||||
spl_autoload_register(array(new self(), 'autoload'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,7 @@ class Autoloader
|
||||
$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
|
||||
|
||||
if (is_file($filepath)) {
|
||||
require($filepath);
|
||||
require $filepath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+52
-27
@@ -11,15 +11,13 @@
|
||||
|
||||
namespace Predis;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use UnexpectedValueException;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\RawCommand;
|
||||
use Predis\Command\ScriptCommand;
|
||||
use Predis\Configuration\Options;
|
||||
use Predis\Configuration\OptionsInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Connection\AggregateConnectionInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Connection\ParametersInterface;
|
||||
use Predis\Monitor\Consumer as MonitorConsumer;
|
||||
use Predis\Pipeline\Pipeline;
|
||||
@@ -40,9 +38,9 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class Client implements ClientInterface
|
||||
class Client implements ClientInterface, \IteratorAggregate
|
||||
{
|
||||
const VERSION = '1.1.0-dev';
|
||||
const VERSION = '1.1.11-dev';
|
||||
|
||||
protected $connection;
|
||||
protected $options;
|
||||
@@ -66,9 +64,9 @@ class Client implements ClientInterface
|
||||
*
|
||||
* @param mixed $options Client options.
|
||||
*
|
||||
* @return OptionsInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return OptionsInterface
|
||||
*/
|
||||
protected function createOptions($options)
|
||||
{
|
||||
@@ -80,7 +78,7 @@ class Client implements ClientInterface
|
||||
return $options;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Invalid type for client options.");
|
||||
throw new \InvalidArgumentException('Invalid type for client options.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,9 +96,9 @@ class Client implements ClientInterface
|
||||
*
|
||||
* @param mixed $parameters Connection parameters or connection instance.
|
||||
*
|
||||
* @return ConnectionInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return ConnectionInterface
|
||||
*/
|
||||
protected function createConnection($parameters)
|
||||
{
|
||||
@@ -122,13 +120,18 @@ class Client implements ClientInterface
|
||||
if ($options->defined('aggregate')) {
|
||||
$initializer = $this->getConnectionInitializerWrapper($options->aggregate);
|
||||
$connection = $initializer($parameters, $options);
|
||||
} else {
|
||||
if ($options->defined('replication') && $replication = $options->replication) {
|
||||
$connection = $replication;
|
||||
} else {
|
||||
$connection = $options->cluster;
|
||||
}
|
||||
} elseif ($options->defined('replication')) {
|
||||
$replication = $options->replication;
|
||||
|
||||
if ($replication instanceof AggregateConnectionInterface) {
|
||||
$connection = $replication;
|
||||
$options->connections->aggregate($connection, $parameters);
|
||||
} else {
|
||||
$initializer = $this->getConnectionInitializerWrapper($replication);
|
||||
$connection = $initializer($parameters, $options);
|
||||
}
|
||||
} else {
|
||||
$connection = $options->cluster;
|
||||
$options->connections->aggregate($connection, $parameters);
|
||||
}
|
||||
|
||||
@@ -142,7 +145,7 @@ class Client implements ClientInterface
|
||||
return $connection;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Invalid type for connection parameters.');
|
||||
throw new \InvalidArgumentException('Invalid type for connection parameters.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +162,7 @@ class Client implements ClientInterface
|
||||
$connection = call_user_func_array($callable, func_get_args());
|
||||
|
||||
if (!$connection instanceof ConnectionInterface) {
|
||||
throw new UnexpectedValueException(
|
||||
throw new \UnexpectedValueException(
|
||||
'The callable connection initializer returned an invalid type.'
|
||||
);
|
||||
}
|
||||
@@ -191,14 +194,14 @@ class Client implements ClientInterface
|
||||
*
|
||||
* @param string $connectionID Identifier of a connection.
|
||||
*
|
||||
* @return Client
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
public function getClientFor($connectionID)
|
||||
{
|
||||
if (!$connection = $this->getConnectionById($connectionID)) {
|
||||
throw new InvalidArgumentException("Invalid connection ID: $connectionID.");
|
||||
throw new \InvalidArgumentException("Invalid connection ID: $connectionID.");
|
||||
}
|
||||
|
||||
return new static($connection, $this->options);
|
||||
@@ -255,9 +258,9 @@ class Client implements ClientInterface
|
||||
*
|
||||
* @param string $connectionID Index or alias of the single connection.
|
||||
*
|
||||
* @return Connection\NodeConnectionInterface
|
||||
*
|
||||
* @throws NotSupportedException
|
||||
*
|
||||
* @return Connection\NodeConnectionInterface
|
||||
*/
|
||||
public function getConnectionById($connectionID)
|
||||
{
|
||||
@@ -275,7 +278,7 @@ class Client implements ClientInterface
|
||||
* applying any prefix to keys or throwing exceptions on Redis errors even
|
||||
* regardless of client options.
|
||||
*
|
||||
* It is possibile to indentify Redis error responses from normal responses
|
||||
* It is possible to identify Redis error responses from normal responses
|
||||
* using the second optional argument which is populated by reference.
|
||||
*
|
||||
* @param array $arguments Command arguments as defined by the command signature.
|
||||
@@ -344,9 +347,9 @@ class Client implements ClientInterface
|
||||
* @param CommandInterface $command Redis command that generated the error.
|
||||
* @param ErrorResponseInterface $response Instance of the error response.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws ServerException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response)
|
||||
{
|
||||
@@ -478,7 +481,7 @@ class Client implements ClientInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new publis/subscribe context and returns it, or starts its loop
|
||||
* Creates a new publish/subscribe context and returns it, or starts its loop
|
||||
* inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed ... Array of options, a callable for execution, or both.
|
||||
@@ -522,4 +525,26 @@ class Client implements ClientInterface
|
||||
{
|
||||
return new MonitorConsumer($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable<string, static>
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
$clients = array();
|
||||
$connection = $this->getConnection();
|
||||
|
||||
if (!$connection instanceof \Traversable) {
|
||||
return new \ArrayIterator(array(
|
||||
(string) $connection => new static($connection, $this->getOptions())
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($connection as $node) {
|
||||
$clients[(string) $node] = new static($node, $this->getOptions());
|
||||
}
|
||||
|
||||
return new \ArrayIterator($clients);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use Predis\Command\CommandInterface;
|
||||
/**
|
||||
* Interface defining a client-side context such as a pipeline or transaction.
|
||||
*
|
||||
* @method $this del(array $keys)
|
||||
* @method $this del(array|string $keys)
|
||||
* @method $this dump($key)
|
||||
* @method $this exists($key)
|
||||
* @method $this expire($key, $seconds)
|
||||
@@ -38,6 +38,8 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this append($key, $value)
|
||||
* @method $this bitcount($key, $start = null, $end = null)
|
||||
* @method $this bitop($operation, $destkey, $key)
|
||||
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
|
||||
* @method $this bitpos($key, $bit, $start = null, $end = null)
|
||||
* @method $this decr($key)
|
||||
* @method $this decrby($key, $decrement)
|
||||
* @method $this get($key)
|
||||
@@ -71,15 +73,16 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this hset($key, $field, $value)
|
||||
* @method $this hsetnx($key, $field, $value)
|
||||
* @method $this hvals($key)
|
||||
* @method $this blpop(array $keys, $timeout)
|
||||
* @method $this brpop(array $keys, $timeout)
|
||||
* @method $this hstrlen($key, $field)
|
||||
* @method $this blpop(array|string $keys, $timeout)
|
||||
* @method $this brpop(array|string $keys, $timeout)
|
||||
* @method $this brpoplpush($source, $destination, $timeout)
|
||||
* @method $this lindex($key, $index)
|
||||
* @method $this linsert($key, $whence, $pivot, $value)
|
||||
* @method $this llen($key)
|
||||
* @method $this lpop($key)
|
||||
* @method $this lpush($key, array $values)
|
||||
* @method $this lpushx($key, $value)
|
||||
* @method $this lpushx($key, array $values)
|
||||
* @method $this lrange($key, $start, $stop)
|
||||
* @method $this lrem($key, $count, $value)
|
||||
* @method $this lset($key, $index, $value)
|
||||
@@ -87,27 +90,27 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this rpop($key)
|
||||
* @method $this rpoplpush($source, $destination)
|
||||
* @method $this rpush($key, array $values)
|
||||
* @method $this rpushx($key, $value)
|
||||
* @method $this rpushx($key, array $values)
|
||||
* @method $this sadd($key, array $members)
|
||||
* @method $this scard($key)
|
||||
* @method $this sdiff(array $keys)
|
||||
* @method $this sdiffstore($destination, array $keys)
|
||||
* @method $this sinter(array $keys)
|
||||
* @method $this sinterstore($destination, array $keys)
|
||||
* @method $this sdiff(array|string $keys)
|
||||
* @method $this sdiffstore($destination, array|string $keys)
|
||||
* @method $this sinter(array|string $keys)
|
||||
* @method $this sinterstore($destination, array|string $keys)
|
||||
* @method $this sismember($key, $member)
|
||||
* @method $this smembers($key)
|
||||
* @method $this smove($source, $destination, $member)
|
||||
* @method $this spop($key)
|
||||
* @method $this spop($key, $count = null)
|
||||
* @method $this srandmember($key, $count = null)
|
||||
* @method $this srem($key, $member)
|
||||
* @method $this sscan($key, $cursor, array $options = null)
|
||||
* @method $this sunion(array $keys)
|
||||
* @method $this sunionstore($destination, array $keys)
|
||||
* @method $this sunion(array|string $keys)
|
||||
* @method $this sunionstore($destination, array|string $keys)
|
||||
* @method $this zadd($key, array $membersAndScoresDictionary)
|
||||
* @method $this zcard($key)
|
||||
* @method $this zcount($key, $min, $max)
|
||||
* @method $this zincrby($key, $increment, $member)
|
||||
* @method $this zinterstore($destination, array $keys, array $options = null)
|
||||
* @method $this zinterstore($destination, array|string $keys, array $options = null)
|
||||
* @method $this zrange($key, $start, $stop, array $options = null)
|
||||
* @method $this zrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method $this zrank($key, $member)
|
||||
@@ -115,17 +118,18 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this zremrangebyrank($key, $start, $stop)
|
||||
* @method $this zremrangebyscore($key, $min, $max)
|
||||
* @method $this zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method $this zrevrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method $this zrevrangebyscore($key, $max, $min, array $options = null)
|
||||
* @method $this zrevrank($key, $member)
|
||||
* @method $this zunionstore($destination, array $keys, array $options = null)
|
||||
* @method $this zunionstore($destination, array|string $keys, array $options = null)
|
||||
* @method $this zscore($key, $member)
|
||||
* @method $this zscan($key, $cursor, array $options = null)
|
||||
* @method $this zrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method $this zrevrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method $this zremrangebylex($key, $min, $max)
|
||||
* @method $this zlexcount($key, $min, $max)
|
||||
* @method $this pfadd($key, array $elements)
|
||||
* @method $this pfmerge($destinationKey, array $sourceKeys)
|
||||
* @method $this pfcount(array $keys)
|
||||
* @method $this pfmerge($destinationKey, array|string $sourceKeys)
|
||||
* @method $this pfcount(array|string $keys)
|
||||
* @method $this pubsub($subcommand, $argument)
|
||||
* @method $this publish($channel, $message)
|
||||
* @method $this discard()
|
||||
@@ -154,12 +158,17 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this slowlog($subcommand, $argument = null)
|
||||
* @method $this time()
|
||||
* @method $this command()
|
||||
* @method $this geoadd($key, $longitude, $latitude, $member)
|
||||
* @method $this geohash($key, array $members)
|
||||
* @method $this geopos($key, array $members)
|
||||
* @method $this geodist($key, $member1, $member2, $unit = null)
|
||||
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
|
||||
* @method $this georadiusbymember($key, $member, $radius, $unit, array $options = null)
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface ClientContextInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Sends the specified command instance to Redis.
|
||||
*
|
||||
|
||||
+148
-138
@@ -24,144 +24,154 @@ use Predis\Profile\ProfileInterface;
|
||||
* and more friendly interface to ease programming which is described in the
|
||||
* following list of methods:
|
||||
*
|
||||
* @method int del(array $keys)
|
||||
* @method string dump($key)
|
||||
* @method int exists($key)
|
||||
* @method int expire($key, $seconds)
|
||||
* @method int expireat($key, $timestamp)
|
||||
* @method array keys($pattern)
|
||||
* @method int move($key, $db)
|
||||
* @method mixed object($subcommand, $key)
|
||||
* @method int persist($key)
|
||||
* @method int pexpire($key, $milliseconds)
|
||||
* @method int pexpireat($key, $timestamp)
|
||||
* @method int pttl($key)
|
||||
* @method string randomkey()
|
||||
* @method mixed rename($key, $target)
|
||||
* @method int renamenx($key, $target)
|
||||
* @method array scan($cursor, array $options = null)
|
||||
* @method array sort($key, array $options = null)
|
||||
* @method int ttl($key)
|
||||
* @method mixed type($key)
|
||||
* @method int append($key, $value)
|
||||
* @method int bitcount($key, $start = null, $end = null)
|
||||
* @method int bitop($operation, $destkey, $key)
|
||||
* @method int decr($key)
|
||||
* @method int decrby($key, $decrement)
|
||||
* @method string get($key)
|
||||
* @method int getbit($key, $offset)
|
||||
* @method string getrange($key, $start, $end)
|
||||
* @method string getset($key, $value)
|
||||
* @method int incr($key)
|
||||
* @method int incrby($key, $increment)
|
||||
* @method string incrbyfloat($key, $increment)
|
||||
* @method array mget(array $keys)
|
||||
* @method mixed mset(array $dictionary)
|
||||
* @method int msetnx(array $dictionary)
|
||||
* @method mixed psetex($key, $milliseconds, $value)
|
||||
* @method mixed set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method int setbit($key, $offset, $value)
|
||||
* @method int setex($key, $seconds, $value)
|
||||
* @method int setnx($key, $value)
|
||||
* @method int setrange($key, $offset, $value)
|
||||
* @method int strlen($key)
|
||||
* @method int hdel($key, array $fields)
|
||||
* @method int hexists($key, $field)
|
||||
* @method string hget($key, $field)
|
||||
* @method array hgetall($key)
|
||||
* @method int hincrby($key, $field, $increment)
|
||||
* @method string hincrbyfloat($key, $field, $increment)
|
||||
* @method array hkeys($key)
|
||||
* @method int hlen($key)
|
||||
* @method array hmget($key, array $fields)
|
||||
* @method mixed hmset($key, array $dictionary)
|
||||
* @method array hscan($key, $cursor, array $options = null)
|
||||
* @method int hset($key, $field, $value)
|
||||
* @method int hsetnx($key, $field, $value)
|
||||
* @method array hvals($key)
|
||||
* @method array blpop(array $keys, $timeout)
|
||||
* @method array brpop(array $keys, $timeout)
|
||||
* @method array brpoplpush($source, $destination, $timeout)
|
||||
* @method string lindex($key, $index)
|
||||
* @method int linsert($key, $whence, $pivot, $value)
|
||||
* @method int llen($key)
|
||||
* @method string lpop($key)
|
||||
* @method int lpush($key, array $values)
|
||||
* @method int lpushx($key, $value)
|
||||
* @method array lrange($key, $start, $stop)
|
||||
* @method int lrem($key, $count, $value)
|
||||
* @method mixed lset($key, $index, $value)
|
||||
* @method mixed ltrim($key, $start, $stop)
|
||||
* @method string rpop($key)
|
||||
* @method string rpoplpush($source, $destination)
|
||||
* @method int rpush($key, array $values)
|
||||
* @method int rpushx($key, $value)
|
||||
* @method int sadd($key, array $members)
|
||||
* @method int scard($key)
|
||||
* @method array sdiff(array $keys)
|
||||
* @method int sdiffstore($destination, array $keys)
|
||||
* @method array sinter(array $keys)
|
||||
* @method int sinterstore($destination, array $keys)
|
||||
* @method int sismember($key, $member)
|
||||
* @method array smembers($key)
|
||||
* @method int smove($source, $destination, $member)
|
||||
* @method string spop($key)
|
||||
* @method string srandmember($key, $count = null)
|
||||
* @method int srem($key, $member)
|
||||
* @method array sscan($key, $cursor, array $options = null)
|
||||
* @method array sunion(array $keys)
|
||||
* @method int sunionstore($destination, array $keys)
|
||||
* @method int zadd($key, array $membersAndScoresDictionary)
|
||||
* @method int zcard($key)
|
||||
* @method string zcount($key, $min, $max)
|
||||
* @method string zincrby($key, $increment, $member)
|
||||
* @method int zinterstore($destination, array $keys, array $options = null)
|
||||
* @method array zrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method int zrank($key, $member)
|
||||
* @method int zrem($key, $member)
|
||||
* @method int zremrangebyrank($key, $start, $stop)
|
||||
* @method int zremrangebyscore($key, $min, $max)
|
||||
* @method array zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method int zrevrank($key, $member)
|
||||
* @method int zunionstore($destination, array $keys, array $options = null)
|
||||
* @method string zscore($key, $member)
|
||||
* @method array zscan($key, $cursor, array $options = null)
|
||||
* @method array zrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method int zremrangebylex($key, $min, $max)
|
||||
* @method int zlexcount($key, $min, $max)
|
||||
* @method int pfadd($key, array $elements)
|
||||
* @method mixed pfmerge($destinationKey, array $sourceKeys)
|
||||
* @method int pfcount(array $keys)
|
||||
* @method mixed pubsub($subcommand, $argument)
|
||||
* @method int publish($channel, $message)
|
||||
* @method mixed discard()
|
||||
* @method array exec()
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method mixed watch($key)
|
||||
* @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed script($subcommand, $argument = null)
|
||||
* @method mixed auth($password)
|
||||
* @method string echo($message)
|
||||
* @method mixed ping($message = null)
|
||||
* @method mixed select($database)
|
||||
* @method mixed bgrewriteaof()
|
||||
* @method mixed bgsave()
|
||||
* @method mixed client($subcommand, $argument = null)
|
||||
* @method mixed config($subcommand, $argument = null)
|
||||
* @method int dbsize()
|
||||
* @method mixed flushall()
|
||||
* @method mixed flushdb()
|
||||
* @method array info($section = null)
|
||||
* @method int lastsave()
|
||||
* @method mixed save()
|
||||
* @method mixed slaveof($host, $port)
|
||||
* @method mixed slowlog($subcommand, $argument = null)
|
||||
* @method array time()
|
||||
* @method array command()
|
||||
* @method int del(array|string $keys)
|
||||
* @method string|null dump($key)
|
||||
* @method int exists($key)
|
||||
* @method int expire($key, $seconds)
|
||||
* @method int expireat($key, $timestamp)
|
||||
* @method array keys($pattern)
|
||||
* @method int move($key, $db)
|
||||
* @method mixed object($subcommand, $key)
|
||||
* @method int persist($key)
|
||||
* @method int pexpire($key, $milliseconds)
|
||||
* @method int pexpireat($key, $timestamp)
|
||||
* @method int pttl($key)
|
||||
* @method string|null randomkey()
|
||||
* @method mixed rename($key, $target)
|
||||
* @method int renamenx($key, $target)
|
||||
* @method array scan($cursor, array $options = null)
|
||||
* @method array sort($key, array $options = null)
|
||||
* @method int ttl($key)
|
||||
* @method mixed type($key)
|
||||
* @method int append($key, $value)
|
||||
* @method int bitcount($key, $start = null, $end = null)
|
||||
* @method int bitop($operation, $destkey, $key)
|
||||
* @method array|null bitfield($key, $subcommand, ...$subcommandArg)
|
||||
* @method int bitpos($key, $bit, $start = null, $end = null)
|
||||
* @method int decr($key)
|
||||
* @method int decrby($key, $decrement)
|
||||
* @method string|null get($key)
|
||||
* @method int getbit($key, $offset)
|
||||
* @method string getrange($key, $start, $end)
|
||||
* @method string|null getset($key, $value)
|
||||
* @method int incr($key)
|
||||
* @method int incrby($key, $increment)
|
||||
* @method string incrbyfloat($key, $increment)
|
||||
* @method array mget(array $keys)
|
||||
* @method mixed mset(array $dictionary)
|
||||
* @method int msetnx(array $dictionary)
|
||||
* @method mixed psetex($key, $milliseconds, $value)
|
||||
* @method mixed set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method int setbit($key, $offset, $value)
|
||||
* @method int setex($key, $seconds, $value)
|
||||
* @method int setnx($key, $value)
|
||||
* @method int setrange($key, $offset, $value)
|
||||
* @method int strlen($key)
|
||||
* @method int hdel($key, array $fields)
|
||||
* @method int hexists($key, $field)
|
||||
* @method string|null hget($key, $field)
|
||||
* @method array hgetall($key)
|
||||
* @method int hincrby($key, $field, $increment)
|
||||
* @method string hincrbyfloat($key, $field, $increment)
|
||||
* @method array hkeys($key)
|
||||
* @method int hlen($key)
|
||||
* @method array hmget($key, array $fields)
|
||||
* @method mixed hmset($key, array $dictionary)
|
||||
* @method array hscan($key, $cursor, array $options = null)
|
||||
* @method int hset($key, $field, $value)
|
||||
* @method int hsetnx($key, $field, $value)
|
||||
* @method array hvals($key)
|
||||
* @method int hstrlen($key, $field)
|
||||
* @method array|null blpop(array|string $keys, $timeout)
|
||||
* @method array|null brpop(array|string $keys, $timeout)
|
||||
* @method string|null brpoplpush($source, $destination, $timeout)
|
||||
* @method string|null lindex($key, $index)
|
||||
* @method int linsert($key, $whence, $pivot, $value)
|
||||
* @method int llen($key)
|
||||
* @method string|null lpop($key)
|
||||
* @method int lpush($key, array $values)
|
||||
* @method int lpushx($key, array $values)
|
||||
* @method array lrange($key, $start, $stop)
|
||||
* @method int lrem($key, $count, $value)
|
||||
* @method mixed lset($key, $index, $value)
|
||||
* @method mixed ltrim($key, $start, $stop)
|
||||
* @method string|null rpop($key)
|
||||
* @method string|null rpoplpush($source, $destination)
|
||||
* @method int rpush($key, array $values)
|
||||
* @method int rpushx($key, array $values)
|
||||
* @method int sadd($key, array $members)
|
||||
* @method int scard($key)
|
||||
* @method array sdiff(array|string $keys)
|
||||
* @method int sdiffstore($destination, array|string $keys)
|
||||
* @method array sinter(array|string $keys)
|
||||
* @method int sinterstore($destination, array|string $keys)
|
||||
* @method int sismember($key, $member)
|
||||
* @method array smembers($key)
|
||||
* @method int smove($source, $destination, $member)
|
||||
* @method string|null spop($key, $count = null)
|
||||
* @method string|null srandmember($key, $count = null)
|
||||
* @method int srem($key, $member)
|
||||
* @method array sscan($key, $cursor, array $options = null)
|
||||
* @method array sunion(array|string $keys)
|
||||
* @method int sunionstore($destination, array|string $keys)
|
||||
* @method int zadd($key, array $membersAndScoresDictionary)
|
||||
* @method int zcard($key)
|
||||
* @method string zcount($key, $min, $max)
|
||||
* @method string zincrby($key, $increment, $member)
|
||||
* @method int zinterstore($destination, array|string $keys, array $options = null)
|
||||
* @method array zrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method int|null zrank($key, $member)
|
||||
* @method int zrem($key, $member)
|
||||
* @method int zremrangebyrank($key, $start, $stop)
|
||||
* @method int zremrangebyscore($key, $min, $max)
|
||||
* @method array zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebyscore($key, $max, $min, array $options = null)
|
||||
* @method int|null zrevrank($key, $member)
|
||||
* @method int zunionstore($destination, array|string $keys, array $options = null)
|
||||
* @method string|null zscore($key, $member)
|
||||
* @method array zscan($key, $cursor, array $options = null)
|
||||
* @method array zrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method array zrevrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method int zremrangebylex($key, $min, $max)
|
||||
* @method int zlexcount($key, $min, $max)
|
||||
* @method int pfadd($key, array $elements)
|
||||
* @method mixed pfmerge($destinationKey, array|string $sourceKeys)
|
||||
* @method int pfcount(array|string $keys)
|
||||
* @method mixed pubsub($subcommand, $argument)
|
||||
* @method int publish($channel, $message)
|
||||
* @method mixed discard()
|
||||
* @method array|null exec()
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method mixed watch($key)
|
||||
* @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method mixed script($subcommand, $argument = null)
|
||||
* @method mixed auth($password)
|
||||
* @method string echo($message)
|
||||
* @method mixed ping($message = null)
|
||||
* @method mixed select($database)
|
||||
* @method mixed bgrewriteaof()
|
||||
* @method mixed bgsave()
|
||||
* @method mixed client($subcommand, $argument = null)
|
||||
* @method mixed config($subcommand, $argument = null)
|
||||
* @method int dbsize()
|
||||
* @method mixed flushall()
|
||||
* @method mixed flushdb()
|
||||
* @method array info($section = null)
|
||||
* @method int lastsave()
|
||||
* @method mixed save()
|
||||
* @method mixed slaveof($host, $port)
|
||||
* @method mixed slowlog($subcommand, $argument = null)
|
||||
* @method array time()
|
||||
* @method array command()
|
||||
* @method int geoadd($key, $longitude, $latitude, $member)
|
||||
* @method array geohash($key, array $members)
|
||||
* @method array geopos($key, array $members)
|
||||
* @method string|null geodist($key, $member1, $member2, $unit = null)
|
||||
* @method array georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
|
||||
* @method array georadiusbymember($key, $member, $radius, $unit, array $options = null)
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
|
||||
+181
-110
@@ -11,7 +11,6 @@
|
||||
|
||||
namespace Predis\Cluster;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\ScriptCommand;
|
||||
|
||||
@@ -44,126 +43,136 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
|
||||
return array(
|
||||
/* commands operating on the key space */
|
||||
'EXISTS' => $getKeyFromFirstArgument,
|
||||
'DEL' => $getKeyFromAllArguments,
|
||||
'TYPE' => $getKeyFromFirstArgument,
|
||||
'EXPIRE' => $getKeyFromFirstArgument,
|
||||
'EXPIREAT' => $getKeyFromFirstArgument,
|
||||
'PERSIST' => $getKeyFromFirstArgument,
|
||||
'PEXPIRE' => $getKeyFromFirstArgument,
|
||||
'PEXPIREAT' => $getKeyFromFirstArgument,
|
||||
'TTL' => $getKeyFromFirstArgument,
|
||||
'PTTL' => $getKeyFromFirstArgument,
|
||||
'SORT' => $getKeyFromFirstArgument, // TODO
|
||||
'DUMP' => $getKeyFromFirstArgument,
|
||||
'RESTORE' => $getKeyFromFirstArgument,
|
||||
'EXISTS' => $getKeyFromAllArguments,
|
||||
'DEL' => $getKeyFromAllArguments,
|
||||
'TYPE' => $getKeyFromFirstArgument,
|
||||
'EXPIRE' => $getKeyFromFirstArgument,
|
||||
'EXPIREAT' => $getKeyFromFirstArgument,
|
||||
'PERSIST' => $getKeyFromFirstArgument,
|
||||
'PEXPIRE' => $getKeyFromFirstArgument,
|
||||
'PEXPIREAT' => $getKeyFromFirstArgument,
|
||||
'TTL' => $getKeyFromFirstArgument,
|
||||
'PTTL' => $getKeyFromFirstArgument,
|
||||
'SORT' => array($this, 'getKeyFromSortCommand'),
|
||||
'DUMP' => $getKeyFromFirstArgument,
|
||||
'RESTORE' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on string values */
|
||||
'APPEND' => $getKeyFromFirstArgument,
|
||||
'DECR' => $getKeyFromFirstArgument,
|
||||
'DECRBY' => $getKeyFromFirstArgument,
|
||||
'GET' => $getKeyFromFirstArgument,
|
||||
'GETBIT' => $getKeyFromFirstArgument,
|
||||
'MGET' => $getKeyFromAllArguments,
|
||||
'SET' => $getKeyFromFirstArgument,
|
||||
'GETRANGE' => $getKeyFromFirstArgument,
|
||||
'GETSET' => $getKeyFromFirstArgument,
|
||||
'INCR' => $getKeyFromFirstArgument,
|
||||
'INCRBY' => $getKeyFromFirstArgument,
|
||||
'INCRBYFLOAT' => $getKeyFromFirstArgument,
|
||||
'SETBIT' => $getKeyFromFirstArgument,
|
||||
'SETEX' => $getKeyFromFirstArgument,
|
||||
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'SETNX' => $getKeyFromFirstArgument,
|
||||
'SETRANGE' => $getKeyFromFirstArgument,
|
||||
'STRLEN' => $getKeyFromFirstArgument,
|
||||
'SUBSTR' => $getKeyFromFirstArgument,
|
||||
'BITOP' => array($this, 'getKeyFromBitOp'),
|
||||
'BITCOUNT' => $getKeyFromFirstArgument,
|
||||
'APPEND' => $getKeyFromFirstArgument,
|
||||
'DECR' => $getKeyFromFirstArgument,
|
||||
'DECRBY' => $getKeyFromFirstArgument,
|
||||
'GET' => $getKeyFromFirstArgument,
|
||||
'GETBIT' => $getKeyFromFirstArgument,
|
||||
'MGET' => $getKeyFromAllArguments,
|
||||
'SET' => $getKeyFromFirstArgument,
|
||||
'GETRANGE' => $getKeyFromFirstArgument,
|
||||
'GETSET' => $getKeyFromFirstArgument,
|
||||
'INCR' => $getKeyFromFirstArgument,
|
||||
'INCRBY' => $getKeyFromFirstArgument,
|
||||
'INCRBYFLOAT' => $getKeyFromFirstArgument,
|
||||
'SETBIT' => $getKeyFromFirstArgument,
|
||||
'SETEX' => $getKeyFromFirstArgument,
|
||||
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'SETNX' => $getKeyFromFirstArgument,
|
||||
'SETRANGE' => $getKeyFromFirstArgument,
|
||||
'STRLEN' => $getKeyFromFirstArgument,
|
||||
'SUBSTR' => $getKeyFromFirstArgument,
|
||||
'BITOP' => array($this, 'getKeyFromBitOp'),
|
||||
'BITCOUNT' => $getKeyFromFirstArgument,
|
||||
'BITFIELD' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on lists */
|
||||
'LINSERT' => $getKeyFromFirstArgument,
|
||||
'LINDEX' => $getKeyFromFirstArgument,
|
||||
'LLEN' => $getKeyFromFirstArgument,
|
||||
'LPOP' => $getKeyFromFirstArgument,
|
||||
'RPOP' => $getKeyFromFirstArgument,
|
||||
'RPOPLPUSH' => $getKeyFromAllArguments,
|
||||
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'LPUSH' => $getKeyFromFirstArgument,
|
||||
'LPUSHX' => $getKeyFromFirstArgument,
|
||||
'RPUSH' => $getKeyFromFirstArgument,
|
||||
'RPUSHX' => $getKeyFromFirstArgument,
|
||||
'LRANGE' => $getKeyFromFirstArgument,
|
||||
'LREM' => $getKeyFromFirstArgument,
|
||||
'LSET' => $getKeyFromFirstArgument,
|
||||
'LTRIM' => $getKeyFromFirstArgument,
|
||||
'LINSERT' => $getKeyFromFirstArgument,
|
||||
'LINDEX' => $getKeyFromFirstArgument,
|
||||
'LLEN' => $getKeyFromFirstArgument,
|
||||
'LPOP' => $getKeyFromFirstArgument,
|
||||
'RPOP' => $getKeyFromFirstArgument,
|
||||
'RPOPLPUSH' => $getKeyFromAllArguments,
|
||||
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'LPUSH' => $getKeyFromFirstArgument,
|
||||
'LPUSHX' => $getKeyFromFirstArgument,
|
||||
'RPUSH' => $getKeyFromFirstArgument,
|
||||
'RPUSHX' => $getKeyFromFirstArgument,
|
||||
'LRANGE' => $getKeyFromFirstArgument,
|
||||
'LREM' => $getKeyFromFirstArgument,
|
||||
'LSET' => $getKeyFromFirstArgument,
|
||||
'LTRIM' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on sets */
|
||||
'SADD' => $getKeyFromFirstArgument,
|
||||
'SCARD' => $getKeyFromFirstArgument,
|
||||
'SDIFF' => $getKeyFromAllArguments,
|
||||
'SDIFFSTORE' => $getKeyFromAllArguments,
|
||||
'SINTER' => $getKeyFromAllArguments,
|
||||
'SINTERSTORE' => $getKeyFromAllArguments,
|
||||
'SUNION' => $getKeyFromAllArguments,
|
||||
'SUNIONSTORE' => $getKeyFromAllArguments,
|
||||
'SISMEMBER' => $getKeyFromFirstArgument,
|
||||
'SMEMBERS' => $getKeyFromFirstArgument,
|
||||
'SSCAN' => $getKeyFromFirstArgument,
|
||||
'SPOP' => $getKeyFromFirstArgument,
|
||||
'SRANDMEMBER' => $getKeyFromFirstArgument,
|
||||
'SREM' => $getKeyFromFirstArgument,
|
||||
'SADD' => $getKeyFromFirstArgument,
|
||||
'SCARD' => $getKeyFromFirstArgument,
|
||||
'SDIFF' => $getKeyFromAllArguments,
|
||||
'SDIFFSTORE' => $getKeyFromAllArguments,
|
||||
'SINTER' => $getKeyFromAllArguments,
|
||||
'SINTERSTORE' => $getKeyFromAllArguments,
|
||||
'SUNION' => $getKeyFromAllArguments,
|
||||
'SUNIONSTORE' => $getKeyFromAllArguments,
|
||||
'SISMEMBER' => $getKeyFromFirstArgument,
|
||||
'SMEMBERS' => $getKeyFromFirstArgument,
|
||||
'SSCAN' => $getKeyFromFirstArgument,
|
||||
'SPOP' => $getKeyFromFirstArgument,
|
||||
'SRANDMEMBER' => $getKeyFromFirstArgument,
|
||||
'SREM' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on sorted sets */
|
||||
'ZADD' => $getKeyFromFirstArgument,
|
||||
'ZCARD' => $getKeyFromFirstArgument,
|
||||
'ZCOUNT' => $getKeyFromFirstArgument,
|
||||
'ZINCRBY' => $getKeyFromFirstArgument,
|
||||
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
|
||||
'ZRANGE' => $getKeyFromFirstArgument,
|
||||
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
|
||||
'ZRANK' => $getKeyFromFirstArgument,
|
||||
'ZREM' => $getKeyFromFirstArgument,
|
||||
'ZREMRANGEBYRANK' => $getKeyFromFirstArgument,
|
||||
'ZREMRANGEBYSCORE' => $getKeyFromFirstArgument,
|
||||
'ZREVRANGE' => $getKeyFromFirstArgument,
|
||||
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
|
||||
'ZREVRANK' => $getKeyFromFirstArgument,
|
||||
'ZSCORE' => $getKeyFromFirstArgument,
|
||||
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
|
||||
'ZSCAN' => $getKeyFromFirstArgument,
|
||||
'ZLEXCOUNT' => $getKeyFromFirstArgument,
|
||||
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
|
||||
'ZREMRANGEBYLEX' => $getKeyFromFirstArgument,
|
||||
'ZREVRANGEBYLEX' => $getKeyFromFirstArgument,
|
||||
'ZADD' => $getKeyFromFirstArgument,
|
||||
'ZCARD' => $getKeyFromFirstArgument,
|
||||
'ZCOUNT' => $getKeyFromFirstArgument,
|
||||
'ZINCRBY' => $getKeyFromFirstArgument,
|
||||
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
|
||||
'ZRANGE' => $getKeyFromFirstArgument,
|
||||
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
|
||||
'ZRANK' => $getKeyFromFirstArgument,
|
||||
'ZREM' => $getKeyFromFirstArgument,
|
||||
'ZREMRANGEBYRANK' => $getKeyFromFirstArgument,
|
||||
'ZREMRANGEBYSCORE' => $getKeyFromFirstArgument,
|
||||
'ZREVRANGE' => $getKeyFromFirstArgument,
|
||||
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
|
||||
'ZREVRANK' => $getKeyFromFirstArgument,
|
||||
'ZSCORE' => $getKeyFromFirstArgument,
|
||||
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
|
||||
'ZSCAN' => $getKeyFromFirstArgument,
|
||||
'ZLEXCOUNT' => $getKeyFromFirstArgument,
|
||||
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
|
||||
'ZREMRANGEBYLEX' => $getKeyFromFirstArgument,
|
||||
'ZREVRANGEBYLEX' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on hashes */
|
||||
'HDEL' => $getKeyFromFirstArgument,
|
||||
'HEXISTS' => $getKeyFromFirstArgument,
|
||||
'HGET' => $getKeyFromFirstArgument,
|
||||
'HGETALL' => $getKeyFromFirstArgument,
|
||||
'HMGET' => $getKeyFromFirstArgument,
|
||||
'HMSET' => $getKeyFromFirstArgument,
|
||||
'HINCRBY' => $getKeyFromFirstArgument,
|
||||
'HINCRBYFLOAT' => $getKeyFromFirstArgument,
|
||||
'HKEYS' => $getKeyFromFirstArgument,
|
||||
'HLEN' => $getKeyFromFirstArgument,
|
||||
'HSET' => $getKeyFromFirstArgument,
|
||||
'HSETNX' => $getKeyFromFirstArgument,
|
||||
'HVALS' => $getKeyFromFirstArgument,
|
||||
'HSCAN' => $getKeyFromFirstArgument,
|
||||
'HDEL' => $getKeyFromFirstArgument,
|
||||
'HEXISTS' => $getKeyFromFirstArgument,
|
||||
'HGET' => $getKeyFromFirstArgument,
|
||||
'HGETALL' => $getKeyFromFirstArgument,
|
||||
'HMGET' => $getKeyFromFirstArgument,
|
||||
'HMSET' => $getKeyFromFirstArgument,
|
||||
'HINCRBY' => $getKeyFromFirstArgument,
|
||||
'HINCRBYFLOAT' => $getKeyFromFirstArgument,
|
||||
'HKEYS' => $getKeyFromFirstArgument,
|
||||
'HLEN' => $getKeyFromFirstArgument,
|
||||
'HSET' => $getKeyFromFirstArgument,
|
||||
'HSETNX' => $getKeyFromFirstArgument,
|
||||
'HVALS' => $getKeyFromFirstArgument,
|
||||
'HSCAN' => $getKeyFromFirstArgument,
|
||||
'HSTRLEN' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on HyperLogLog */
|
||||
'PFADD' => $getKeyFromFirstArgument,
|
||||
'PFCOUNT' => $getKeyFromAllArguments,
|
||||
'PFMERGE' => $getKeyFromAllArguments,
|
||||
'PFADD' => $getKeyFromFirstArgument,
|
||||
'PFCOUNT' => $getKeyFromAllArguments,
|
||||
'PFMERGE' => $getKeyFromAllArguments,
|
||||
|
||||
/* scripting */
|
||||
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
|
||||
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
|
||||
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
|
||||
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
|
||||
|
||||
/* commands performing geospatial operations */
|
||||
'GEOADD' => $getKeyFromFirstArgument,
|
||||
'GEOHASH' => $getKeyFromFirstArgument,
|
||||
'GEOPOS' => $getKeyFromFirstArgument,
|
||||
'GEODIST' => $getKeyFromFirstArgument,
|
||||
'GEORADIUS' => array($this, 'getKeyFromGeoradiusCommands'),
|
||||
'GEORADIUSBYMEMBER' => array($this, 'getKeyFromGeoradiusCommands'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -202,8 +211,8 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
}
|
||||
|
||||
if (!is_callable($callback)) {
|
||||
throw new InvalidArgumentException(
|
||||
"The argument must be a callable object or NULL."
|
||||
throw new \InvalidArgumentException(
|
||||
'The argument must be a callable object or NULL.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -261,6 +270,35 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from SORT command.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getKeyFromSortCommand(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$firstKey = $arguments[0];
|
||||
|
||||
if (1 === $argc = count($arguments)) {
|
||||
return $firstKey;
|
||||
}
|
||||
|
||||
$keys = array($firstKey);
|
||||
|
||||
for ($i = 1; $i < $argc; ++$i) {
|
||||
if (strtoupper($arguments[$i]) === 'STORE') {
|
||||
$keys[] = $arguments[++$i];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->checkSameSlotForKeys($keys)) {
|
||||
return $firstKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from BLPOP and BRPOP commands.
|
||||
*
|
||||
@@ -293,6 +331,39 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from GEORADIUS and GEORADIUSBYMEMBER commands.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getKeyFromGeoradiusCommands(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$argc = count($arguments);
|
||||
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
|
||||
|
||||
if ($argc > $startIndex) {
|
||||
$keys = array($arguments[0]);
|
||||
|
||||
for ($i = $startIndex; $i < $argc; ++$i) {
|
||||
$argument = strtoupper($arguments[$i]);
|
||||
if ($argument === 'STORE' || $argument === 'STOREDIST') {
|
||||
$keys[] = $arguments[++$i];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->checkSameSlotForKeys($keys)) {
|
||||
return $arguments[0];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from ZINTERSTORE and ZUNIONSTORE commands.
|
||||
*
|
||||
@@ -364,7 +435,7 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
|
||||
$currentSlot = $this->getSlotByKey($keys[0]);
|
||||
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
for ($i = 1; $i < $count; ++$i) {
|
||||
$nextSlot = $this->getSlotByKey($keys[$i]);
|
||||
|
||||
if ($currentSlot !== $nextSlot) {
|
||||
|
||||
@@ -11,13 +11,11 @@
|
||||
|
||||
namespace Predis\Cluster\Distributor;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Exception class that identifies empty rings.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class EmptyRingException extends Exception
|
||||
class EmptyRingException extends \Exception
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
|
||||
class HashRing implements DistributorInterface, HashGeneratorInterface
|
||||
{
|
||||
const DEFAULT_REPLICAS = 128;
|
||||
const DEFAULT_WEIGHT = 100;
|
||||
const DEFAULT_WEIGHT = 100;
|
||||
|
||||
private $ring;
|
||||
private $ringKeys;
|
||||
@@ -55,7 +55,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
|
||||
// last wins, thus the order in which nodes are added is significant.
|
||||
$this->nodes[] = array(
|
||||
'object' => $node,
|
||||
'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT
|
||||
'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT,
|
||||
);
|
||||
|
||||
$this->reset();
|
||||
@@ -160,8 +160,8 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
|
||||
$nodeHash = $this->getNodeHash($nodeObject);
|
||||
$replicas = (int) round($weightRatio * $totalNodes * $replicas);
|
||||
|
||||
for ($i = 0; $i < $replicas; $i++) {
|
||||
$key = crc32("$nodeHash:$i");
|
||||
for ($i = 0; $i < $replicas; ++$i) {
|
||||
$key = $this->hash("$nodeHash:$i");
|
||||
$ring[$key] = $nodeObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class KetamaRing extends HashRing
|
||||
$nodeHash = $this->getNodeHash($nodeObject);
|
||||
$replicas = (int) floor($weightRatio * $totalNodes * ($replicas / 4));
|
||||
|
||||
for ($i = 0; $i < $replicas; $i++) {
|
||||
for ($i = 0; $i < $replicas; ++$i) {
|
||||
$unpackedDigest = unpack('V4', md5("$nodeHash-$i", true));
|
||||
|
||||
foreach ($unpackedDigest as $key) {
|
||||
|
||||
@@ -61,9 +61,11 @@ class CRC16 implements HashGeneratorInterface
|
||||
// CRC-CCITT-16 algorithm
|
||||
$crc = 0;
|
||||
$CCITT_16 = self::$CCITT_16;
|
||||
|
||||
$value = (string) $value;
|
||||
$strlen = strlen($value);
|
||||
|
||||
for ($i = 0; $i < $strlen; $i++) {
|
||||
for ($i = 0; $i < $strlen; ++$i) {
|
||||
$crc = (($crc << 8) ^ $CCITT_16[($crc >> 8) ^ ord($value[$i])]) & 0xFFFF;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class PredisStrategy extends ClusterStrategy
|
||||
|
||||
$currentKey = $this->extractKeyTag($keys[0]);
|
||||
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
for ($i = 1; $i < $count; ++$i) {
|
||||
$nextKey = $this->extractKeyTag($keys[$i]);
|
||||
|
||||
if ($currentKey !== $nextKey) {
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
namespace Predis\Cluster;
|
||||
|
||||
use Predis\NotSupportedException;
|
||||
use Predis\Cluster\Hash\HashGeneratorInterface;
|
||||
use Predis\Cluster\Hash\CRC16;
|
||||
use Predis\Cluster\Hash\HashGeneratorInterface;
|
||||
use Predis\NotSupportedException;
|
||||
|
||||
/**
|
||||
* Default class used by Predis to calculate hashes out of keys of
|
||||
@@ -40,7 +40,7 @@ class RedisStrategy extends ClusterStrategy
|
||||
*/
|
||||
public function getSlotByKey($key)
|
||||
{
|
||||
$key = $this->extractKeyTag($key);
|
||||
$key = $this->extractKeyTag($key);
|
||||
$slot = $this->hashGenerator->hash($key) & 0x3FFF;
|
||||
|
||||
return $slot;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
namespace Predis\Collection\Iterator;
|
||||
|
||||
use Iterator;
|
||||
use Predis\ClientInterface;
|
||||
use Predis\NotSupportedException;
|
||||
|
||||
@@ -28,7 +27,7 @@ use Predis\NotSupportedException;
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class CursorBasedIterator implements Iterator
|
||||
abstract class CursorBasedIterator implements \Iterator
|
||||
{
|
||||
protected $client;
|
||||
protected $match;
|
||||
@@ -93,7 +92,7 @@ abstract class CursorBasedIterator implements Iterator
|
||||
{
|
||||
$options = array();
|
||||
|
||||
if (strlen($this->match) > 0) {
|
||||
if (strlen(strval($this->match)) > 0) {
|
||||
$options['MATCH'] = $this->match;
|
||||
}
|
||||
|
||||
@@ -133,13 +132,15 @@ abstract class CursorBasedIterator implements Iterator
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position++;
|
||||
++$this->position;
|
||||
$this->current = array_shift($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
$this->reset();
|
||||
@@ -148,7 +149,9 @@ abstract class CursorBasedIterator implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return $this->current;
|
||||
@@ -156,7 +159,9 @@ abstract class CursorBasedIterator implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return $this->position;
|
||||
@@ -164,7 +169,9 @@ abstract class CursorBasedIterator implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
tryFetch: {
|
||||
@@ -184,7 +191,9 @@ abstract class CursorBasedIterator implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return $this->valid;
|
||||
|
||||
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
|
||||
* HSCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* @link http://redis.io/commands/scan
|
||||
*/
|
||||
class HashKey extends CursorBasedIterator
|
||||
@@ -50,6 +51,8 @@ class HashKey extends CursorBasedIterator
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position = key($this->elements);
|
||||
$this->current = array_shift($this->elements);
|
||||
$this->current = current($this->elements);
|
||||
|
||||
unset($this->elements[$this->position]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
|
||||
* SCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* @link http://redis.io/commands/scan
|
||||
*/
|
||||
class Keyspace extends CursorBasedIterator
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
|
||||
namespace Predis\Collection\Iterator;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use Predis\ClientInterface;
|
||||
use Predis\NotSupportedException;
|
||||
|
||||
@@ -27,9 +25,10 @@ use Predis\NotSupportedException;
|
||||
* times (trimmed, deleted, overwritten) during the iteration process.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* @link http://redis.io/commands/lrange
|
||||
*/
|
||||
class ListKey implements Iterator
|
||||
class ListKey implements \Iterator
|
||||
{
|
||||
protected $client;
|
||||
protected $count;
|
||||
@@ -53,7 +52,7 @@ class ListKey implements Iterator
|
||||
$this->requiredCommand($client, 'LRANGE');
|
||||
|
||||
if ((false === $count = filter_var($count, FILTER_VALIDATE_INT)) || $count < 0) {
|
||||
throw new InvalidArgumentException('The $count argument must be a positive integer.');
|
||||
throw new \InvalidArgumentException('The $count argument must be a positive integer.');
|
||||
}
|
||||
|
||||
$this->client = $client;
|
||||
@@ -122,13 +121,15 @@ class ListKey implements Iterator
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position++;
|
||||
++$this->position;
|
||||
$this->current = array_shift($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
$this->reset();
|
||||
@@ -137,7 +138,9 @@ class ListKey implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return $this->current;
|
||||
@@ -145,7 +148,9 @@ class ListKey implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return $this->position;
|
||||
@@ -153,7 +158,9 @@ class ListKey implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
if (!$this->elements && $this->fetchmore) {
|
||||
@@ -169,7 +176,9 @@ class ListKey implements Iterator
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return $this->valid;
|
||||
|
||||
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
|
||||
* command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* @link http://redis.io/commands/scan
|
||||
*/
|
||||
class SetKey extends CursorBasedIterator
|
||||
|
||||
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
|
||||
* ZSCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* @link http://redis.io/commands/scan
|
||||
*/
|
||||
class SortedSetKey extends CursorBasedIterator
|
||||
@@ -49,11 +50,9 @@ class SortedSetKey extends CursorBasedIterator
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
if ($kv = each($this->elements)) {
|
||||
$this->position = $kv[0];
|
||||
$this->current = $kv[1];
|
||||
$this->position = key($this->elements);
|
||||
$this->current = current($this->elements);
|
||||
|
||||
unset($this->elements[$this->position]);
|
||||
}
|
||||
unset($this->elements[$this->position]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ abstract class Command implements CommandInterface
|
||||
*/
|
||||
public static function normalizeArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 1 && is_array($arguments[0])) {
|
||||
if (count($arguments) === 1 && isset($arguments[0]) && is_array($arguments[0])) {
|
||||
return $arguments[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/auth
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionAuth extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/echo
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionEcho extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/ping
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionPing extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/quit
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionQuit extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/select
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionSelect extends Command
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geoadd
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GeospatialGeoAdd extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOADD';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
foreach (array_pop($arguments) as $item) {
|
||||
$arguments = array_merge($arguments, $item);
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geodist
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GeospatialGeoDist extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEODIST';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geohash
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GeospatialGeoHash extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOHASH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
$members = array_pop($arguments);
|
||||
$arguments = array_merge($arguments, $members);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geopos
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GeospatialGeoPos extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOPOS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
$members = array_pop($arguments);
|
||||
$arguments = array_merge($arguments, $members);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/georadius
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GeospatialGeoRadius extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEORADIUS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
{
|
||||
if ($arguments && is_array(end($arguments))) {
|
||||
$options = array_change_key_case(array_pop($arguments), CASE_UPPER);
|
||||
|
||||
if (isset($options['WITHCOORD']) && $options['WITHCOORD'] == true) {
|
||||
$arguments[] = 'WITHCOORD';
|
||||
}
|
||||
|
||||
if (isset($options['WITHDIST']) && $options['WITHDIST'] == true) {
|
||||
$arguments[] = 'WITHDIST';
|
||||
}
|
||||
|
||||
if (isset($options['WITHHASH']) && $options['WITHHASH'] == true) {
|
||||
$arguments[] = 'WITHHASH';
|
||||
}
|
||||
|
||||
if (isset($options['COUNT'])) {
|
||||
$arguments[] = 'COUNT';
|
||||
$arguments[] = $options['COUNT'];
|
||||
}
|
||||
|
||||
if (isset($options['SORT'])) {
|
||||
$arguments[] = strtoupper($options['SORT']);
|
||||
}
|
||||
|
||||
if (isset($options['STORE'])) {
|
||||
$arguments[] = 'STORE';
|
||||
$arguments[] = $options['STORE'];
|
||||
}
|
||||
|
||||
if (isset($options['STOREDIST'])) {
|
||||
$arguments[] = 'STOREDIST';
|
||||
$arguments[] = $options['STOREDIST'];
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/georadiusbymember
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GeospatialGeoRadiusByMember extends GeospatialGeoRadius
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEORADIUSBYMEMBER';
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hdel
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashDelete extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hexists
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashExists extends Command
|
||||
@@ -24,12 +25,4 @@ class HashExists extends Command
|
||||
{
|
||||
return 'HEXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hget
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGet extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hgetall
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGetAll extends Command
|
||||
@@ -32,7 +33,7 @@ class HashGetAll extends Command
|
||||
{
|
||||
$result = array();
|
||||
|
||||
for ($i = 0; $i < count($data); $i++) {
|
||||
for ($i = 0; $i < count($data); ++$i) {
|
||||
$result[$data[$i]] = $data[++$i];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hmget
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGetMultiple extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hincrby
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashIncrementBy extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hincrbyfloat
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashIncrementByFloat extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hkeys
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashKeys extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hlen
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashLength extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hscan
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashScan extends Command
|
||||
@@ -72,7 +73,7 @@ class HashScan extends Command
|
||||
$fields = $data[1];
|
||||
$result = array();
|
||||
|
||||
for ($i = 0; $i < count($fields); $i++) {
|
||||
for ($i = 0; $i < count($fields); ++$i) {
|
||||
$result[$fields[$i]] = $fields[++$i];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hset
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSet extends Command
|
||||
@@ -24,12 +25,4 @@ class HashSet extends Command
|
||||
{
|
||||
return 'HSET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hmset
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSetMultiple extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hsetnx
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSetPreserve extends Command
|
||||
@@ -24,12 +25,4 @@ class HashSetPreserve extends Command
|
||||
{
|
||||
return 'HSETNX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hstrlen
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashStringLength extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HSTRLEN';
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hvals
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashValues extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pfadd
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HyperLogLogAdd extends Command
|
||||
@@ -32,12 +33,4 @@ class HyperLogLogAdd extends Command
|
||||
{
|
||||
return self::normalizeVariadic($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pfcount
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HyperLogLogCount extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pfmerge
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HyperLogLogMerge extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/del
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyDelete extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/dump
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyDump extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/exists
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExists extends Command
|
||||
@@ -24,12 +25,4 @@ class KeyExists extends Command
|
||||
{
|
||||
return 'EXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/expire
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExpire extends Command
|
||||
@@ -24,12 +25,4 @@ class KeyExpire extends Command
|
||||
{
|
||||
return 'EXPIRE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/expireat
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExpireAt extends Command
|
||||
@@ -24,12 +25,4 @@ class KeyExpireAt extends Command
|
||||
{
|
||||
return 'EXPIREAT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/keys
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyKeys extends Command
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/migrate
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyMigrate extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'MIGRATE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
{
|
||||
if (is_array(end($arguments))) {
|
||||
foreach (array_pop($arguments) as $modifier => $value) {
|
||||
$modifier = strtoupper($modifier);
|
||||
|
||||
if ($modifier === 'COPY' && $value == true) {
|
||||
$arguments[] = $modifier;
|
||||
}
|
||||
|
||||
if ($modifier === 'REPLACE' && $value == true) {
|
||||
$arguments[] = $modifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/move
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyMove extends Command
|
||||
@@ -24,12 +25,4 @@ class KeyMove extends Command
|
||||
{
|
||||
return 'MOVE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/persist
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPersist extends Command
|
||||
@@ -24,12 +25,4 @@ class KeyPersist extends Command
|
||||
{
|
||||
return 'PERSIST';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pexpire
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPreciseExpire extends KeyExpire
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pexpireat
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPreciseExpireAt extends KeyExpireAt
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pttl
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPreciseTimeToLive extends KeyTimeToLive
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/randomkey
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRandom extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/rename
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRename extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/renamenx
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRenamePreserve extends KeyRename
|
||||
@@ -24,12 +25,4 @@ class KeyRenamePreserve extends KeyRename
|
||||
{
|
||||
return 'RENAMENX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/restore
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRestore extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/scan
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyScan extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/sort
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeySort extends Command
|
||||
@@ -59,7 +60,6 @@ class KeySort extends Command
|
||||
if (isset($sortParams['LIMIT']) &&
|
||||
is_array($sortParams['LIMIT']) &&
|
||||
count($sortParams['LIMIT']) == 2) {
|
||||
|
||||
$query[] = 'LIMIT';
|
||||
$query[] = $sortParams['LIMIT'][0];
|
||||
$query[] = $sortParams['LIMIT'][1];
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/ttl
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyTimeToLive extends Command
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/type
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyType extends Command
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user