mirror of
https://github.com/predis/predis.git
synced 2026-08-20 07:11:48 +00:00
Compare commits
236 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a1430e99c | |||
| a70971549e | |||
| e88ffc767d | |||
| ce8b3fb683 | |||
| e0b4b2c20a | |||
| 2640062803 | |||
| 1811288009 | |||
| fa643ac20c | |||
| eb1e686ff9 | |||
| f02f3b6d37 | |||
| d72a1b5550 | |||
| 8b466d05df | |||
| b553c6b9d0 | |||
| c10479e238 | |||
| 228ccaebe3 | |||
| 82c256422a | |||
| ee7104d2e5 | |||
| 7c4c4ae58a | |||
| 185e31e080 | |||
| 64b3a4805c | |||
| 5b4e942112 | |||
| b2547fc7f4 | |||
| d34bdd38c3 | |||
| 1028599ac5 | |||
| 822f02b8eb | |||
| 4b47639f9e | |||
| e4872af747 | |||
| c1d34f022f | |||
| 62b421f20e | |||
| 6e3f301588 | |||
| 3dccd6bf87 | |||
| 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 |
+1
-3
@@ -11,7 +11,7 @@ branches:
|
||||
except:
|
||||
- v0.5
|
||||
- v0.6
|
||||
- php5.2_backport
|
||||
- v0.6-PHP_5.2
|
||||
- documentation
|
||||
services: redis-server
|
||||
before_script:
|
||||
@@ -20,6 +20,4 @@ before_script:
|
||||
script:
|
||||
- vendor/bin/phpunit -c phpunit.xml.travisci
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
fast_finish: true
|
||||
|
||||
+170
@@ -1,3 +1,173 @@
|
||||
v2.0.0 (201x-xx-xx)
|
||||
================================================================================
|
||||
|
||||
- Accepted values for some client options have changed, this is the new list of
|
||||
accepted values:
|
||||
|
||||
- `aggregate`: callable returning an aggregate connection.
|
||||
- `cluster`: string value (`predis`, `redis`), callable returning an aggregate
|
||||
connection.
|
||||
- `replication`: string value (`predis`, `sentinel`), callable returning an
|
||||
aggregate connection.
|
||||
- `commands`: command factory, named array mapping command IDs to PHP classes,
|
||||
callable returning a command factory or a named array.
|
||||
- `connections`: connection factory, callable returning a connection factory,
|
||||
named array mapping connection schemes to PHP classes.
|
||||
- `prefix`: string value, command processor, callable.
|
||||
- `exceptions`: boolean.
|
||||
|
||||
Note that both the `cluster` and `replication` options now return a closure
|
||||
acting as initializer instead of an aggregate connection instance.
|
||||
|
||||
- Client option classes now live in the `Predis\Configuration\Option` namespace.
|
||||
|
||||
- Classes for Redis commands have been moved into the new `Predis\Command\Redis`
|
||||
namespace and each class name mirrors the respective Redis command ID.
|
||||
|
||||
- The concept of server profiles is gone, the library now uses a single command
|
||||
factory to create instances of commands classes. The `profile` option has been
|
||||
replaced by the `commands` option accepting `Predis\Command\FactoryInterface`
|
||||
to customize the underlying command factory. The default command factory class
|
||||
used by Predis is `Predis\Command\RedisFactory` and it still allows developers
|
||||
to define or override commands with their own implementations. In addition to
|
||||
that, `Predis\Command\RedisFactory` relies on a convention-over-configuration
|
||||
approach by looking for a suitable class with the same name as the command ID
|
||||
in the `Predis\Command\Redis` when the internal class map does not contain a
|
||||
class associated.
|
||||
|
||||
- The method `Predis\Client::getClientFor($connectionID)` has been replaced by
|
||||
`Predis\Client::on($connectionID, $callable = null)`. This new method returns
|
||||
a new client instance for the specified node just like before when the second
|
||||
argument is omitted, otherwise the callback is invoked and the new client is
|
||||
passed to it. The value returned by the callback is used as the return value
|
||||
of the "on()" method.
|
||||
|
||||
- Changed the signature for the constructor of `Predis\Command\RawCommand`.
|
||||
|
||||
- The `Predis\Connection\Aggregate` namespace has been split into two separate
|
||||
namespaces for cluster backends (`Predis\Connection\Cluster`) and replication
|
||||
backends (`Predis\Connection\Replication`).
|
||||
|
||||
- The methods `switchToMaster()` and `switchToSlave()` have been promoted to be
|
||||
part of `Predis\Connection\Replication\ReplicationInterface` while the method
|
||||
`switchTo($connection)` has been removed from it.
|
||||
|
||||
- The method `Predis\Connection\Cluster\PredisCluster::executeCommandOnNodes()`
|
||||
has been removed as it is possible to achieve the same by iterating over the
|
||||
connection or, even better, over the client instance in order to execute the
|
||||
same command against all of the registered connections.
|
||||
|
||||
|
||||
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)
|
||||
================================================================================
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,52 @@
|
||||
# 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]
|
||||
[![HHVM support][ico-hhvm]][link-hhvm]
|
||||
[![Gitter room][ico-gitter]][link-gitter]
|
||||
|
||||
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 this library 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 RESP Protocol](http://redis.io/topics/protocol). An asynchronous implementation of Predis
|
||||
is available through [Predis\Async](https://github.com/nrk/predis-async) (__experimental__).
|
||||
__ATTENTION:__ you are on the README file of an unstable branch of Predis specifically meant for the
|
||||
development of future releases. This means that the code on this branch is potentially unstable, and
|
||||
breaking change may happen without any prior notice. Do not use it in production environments or use
|
||||
it at your own risk!
|
||||
|
||||
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 and not yet 100% compatible with the _standard_ PHP.
|
||||
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). For an __experimental__ asynchronous
|
||||
implementation of the client you can refer to [Predis\Async](https://github.com/nrk/predis-async).
|
||||
|
||||
More details about this project can be found on the [frequently asked questions](FAQ.md) and on the
|
||||
[wiki](https://github.com/nrk/predis/wiki).
|
||||
More details about this project can be found on the [frequently asked questions](FAQ.md).
|
||||
|
||||
|
||||
## Main features ##
|
||||
|
||||
- Support for a wide range of Redis versions (from __2.0__ to __3.0__) using profiles.
|
||||
- Clustering 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 (write operations on master, read operations on 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 Redis from __2.0__ to __3.2__.
|
||||
- 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.
|
||||
- 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 custom commands and server profiles.
|
||||
- Flexible system for defining custom commands 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/nrk/predis/tags).
|
||||
|
||||
|
||||
### Loading the library ###
|
||||
@@ -52,7 +54,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,11 +63,9 @@ require 'Predis/Autoloader.php';
|
||||
Predis\Autoloader::register();
|
||||
```
|
||||
|
||||
It is possible to create a [phar](http://www.php.net/manual/en/intro.phar.php) archive directly from
|
||||
the repository by launching `bin/create-phar`. The phar contains a stub defining its own autoloader
|
||||
so you just need to `require()` it to start using the library. Ultimately it is possible to generate
|
||||
a single big PHP file containing all the source code simply 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 ###
|
||||
@@ -95,8 +95,34 @@ $client = new Predis\Client([
|
||||
$client = new Predis\Client('tcp://10.0.0.1:6379');
|
||||
```
|
||||
|
||||
Starting with Predis v1.0.2 the client also understands the `redis` scheme in URI strings as defined
|
||||
by the [provisional IANA registration](http://www.iana.org/assignments/uri-schemes/prov/redis).
|
||||
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.
|
||||
@@ -114,54 +140,123 @@ $client = new Predis\Client([
|
||||
|
||||
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($parameters, ['profile' => '2.8', 'prefix' => 'sample:']);
|
||||
$client = new Predis\Client($parameters, ['prefix' => 'sample:']);
|
||||
```
|
||||
|
||||
Options are managed through a mini DI-alike container while their values can be lazily initialized
|
||||
only when needed. This is a list of the options supported by default:
|
||||
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.
|
||||
- `prefix`: prefix string applied to every key 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).
|
||||
- `replication`: specifies a replication backend (`predis`, `sentinel` or callable).
|
||||
- `aggregate`: configures the client with a custom aggregate connection (callable).
|
||||
- `parameters`: list of default connection parameters for aggregate connections.
|
||||
- `commands`: specifies a command factory instance to use through the library.
|
||||
|
||||
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 clustering 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 only 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 operate in a master-slave setup by executing read-only commands on
|
||||
slave nodes and automatically switch to the master node as soon as it detects a command that will
|
||||
perform a write operation. 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);
|
||||
```
|
||||
|
||||
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
|
||||
$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,
|
||||
@@ -169,13 +264,13 @@ when certain Lua scripts do not perform write operations it is possible to provi
|
||||
the client to stick with slaves for their execution:
|
||||
|
||||
```php
|
||||
$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' => function () {
|
||||
// Set scripts that won't trigger a switch from a slave to the master node.
|
||||
$strategy = new Predis\Replication\ReplicationStrategy();
|
||||
$strategy->setScriptReadOnly($LUA_SCRIPT);
|
||||
|
||||
return new Predis\Connection\Aggregate\MasterSlaveReplication($strategy);
|
||||
return new Predis\Connection\Replication\MasterSlaveReplication($strategy);
|
||||
}];
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
@@ -183,29 +278,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
|
||||
[basic](examples/replication_simple.php) and [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, you
|
||||
can specify only a few nodes and the client 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 the 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 ###
|
||||
@@ -255,7 +329,7 @@ of a transaction using CAS you can see [the following example](examples/transact
|
||||
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 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:
|
||||
command classes to define or override commands in the default command factory used by the client:
|
||||
|
||||
```php
|
||||
// Define a new command by extending Predis\Command\Command:
|
||||
@@ -267,9 +341,12 @@ class BrandNewRedisCommand extends Predis\Command\Command
|
||||
}
|
||||
}
|
||||
|
||||
// Inject your command in the current profile:
|
||||
$client = new Predis\Client();
|
||||
$client->getProfile()->defineCommand('newcmd', 'BrandNewRedisCommand');
|
||||
// Inject your command in the current command factory:
|
||||
$client = new Predis\Client($parameters, [
|
||||
'commands' => [
|
||||
'newcmd' => 'BrandNewRedisCommand',
|
||||
],
|
||||
]);
|
||||
|
||||
$response = $client->newcmd();
|
||||
```
|
||||
@@ -286,9 +363,9 @@ $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) directly,
|
||||
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
|
||||
Script commands can be registered in the command factory 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)
|
||||
@@ -314,9 +391,12 @@ LUA;
|
||||
}
|
||||
}
|
||||
|
||||
// Inject the script command in the current profile:
|
||||
$client = new Predis\Client();
|
||||
$client->getProfile()->defineCommand('lpushrand', 'ListPushRandomValue');
|
||||
// Inject the script command in the current command factory:
|
||||
$client = new Predis\Client($parameters, [
|
||||
'commands' => [
|
||||
'lpushrand' => 'ListPushRandomValue',
|
||||
],
|
||||
]);
|
||||
|
||||
$response = $client->lpushrand('random_values', $seed = mt_rand());
|
||||
```
|
||||
@@ -374,15 +454,11 @@ stay consistent while working on the project.
|
||||
__ATTENTION__: Do not ever run the test suite shipped with Predis against instances of Redis running
|
||||
in production environments or containing data you are interested in!
|
||||
|
||||
Predis has a comprehensive test suite covering every aspect of the library. This test suite performs
|
||||
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
|
||||
(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 has a comprehensive test suite covering every aspect of the library and that can optionally
|
||||
perform integration tests against a running instance of Redis (required >= 2.4.0 in order to verify
|
||||
the correct behavior of the implementation of each command. Integration tests for unsupported Redis
|
||||
commands are automatically skipped. If you do not have Redis up and running, integration tests can
|
||||
be disabled. See [the tests README](tests/README.md) for more details about testing this library.
|
||||
|
||||
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).
|
||||
@@ -407,3 +483,17 @@ 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/nrk/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/nrk/predis.svg?style=flat-square
|
||||
[ico-hhvm]: https://img.shields.io/hhvm/predis/predis.svg?style=flat-square
|
||||
[ico-gitter]: https://img.shields.io/gitter/room/nrk/predis.svg?style=flat-square
|
||||
|
||||
[link-packagist]: https://packagist.org/packages/predis/predis
|
||||
[link-travis]: https://travis-ci.org/nrk/predis
|
||||
[link-downloads]: https://packagist.org/packages/predis/predis/stats
|
||||
[link-hhvm]: http://hhvm.h4cc.de/package/predis/predis
|
||||
[link-gitter]: https://gitter.im/nrk/predis
|
||||
|
||||
+18
-15
@@ -15,7 +15,7 @@
|
||||
// of a test case to test a Redis command by specifying the name of the class
|
||||
// in the Predis\Command namespace (only classes in this namespace are valid).
|
||||
// For example, to generate a test case for SET (which is represented by the
|
||||
// Predis\Command\StringSet class):
|
||||
// Predis\Command\Redis\StringSet class):
|
||||
//
|
||||
// $ ./bin/generate-command-test --class=StringSet
|
||||
//
|
||||
@@ -45,6 +45,11 @@ class CommandTestCaseGenerator
|
||||
if (!isset($options['class'])) {
|
||||
throw new RuntimeException("Missing 'class' option.");
|
||||
}
|
||||
|
||||
if (!isset($options['realm'])) {
|
||||
throw new RuntimeException("Missing 'realm' option.");
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
@@ -92,8 +97,12 @@ class CommandTestCaseGenerator
|
||||
throw new RuntimeException("Missing 'class' option.");
|
||||
}
|
||||
|
||||
$options['fqn'] = "Predis\\Command\\{$options['class']}";
|
||||
$options['path'] = "Command/{$options['class']}.php";
|
||||
if (!isset($options['realm'])) {
|
||||
throw new RuntimeException("Missing 'realm' option.");
|
||||
}
|
||||
|
||||
$options['fqn'] = "Predis\\Command\\Redis\\{$options['class']}";
|
||||
$options['path'] = "Command/Redis/{$options['class']}.php";
|
||||
|
||||
$source = __DIR__.'/../src/'.$options['path'];
|
||||
if (!file_exists($source)) {
|
||||
@@ -101,7 +110,7 @@ class CommandTestCaseGenerator
|
||||
}
|
||||
|
||||
if (!isset($options['output'])) {
|
||||
$options['output'] = sprintf("%s/%s", $options['tests'], str_replace('.php', 'Test.php', $options['path']));
|
||||
$options['output'] = sprintf("%s/%s", $options['tests'], str_replace('.php', '_Test.php', $options['path']));
|
||||
}
|
||||
|
||||
return new self($options);
|
||||
@@ -109,18 +118,11 @@ class CommandTestCaseGenerator
|
||||
|
||||
protected function getTestRealm()
|
||||
{
|
||||
if (isset($this->options['realm'])) {
|
||||
if (!$this->options['realm']) {
|
||||
throw new RuntimeException('Invalid value for realm has been sepcified (empty).');
|
||||
}
|
||||
return $this->options['realm'];
|
||||
if (empty($this->options['realm'])) {
|
||||
throw new RuntimeException('Invalid value for realm has been sepcified (empty).');
|
||||
}
|
||||
|
||||
$fqnParts = explode('\\', $this->options['fqn']);
|
||||
$class = array_pop($fqnParts);
|
||||
list($realm,) = preg_split('/([[:upper:]][[:lower:]]+)/', $class, 2, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
return strtolower($realm);
|
||||
return $this->options['realm'];
|
||||
}
|
||||
|
||||
public function generate()
|
||||
@@ -130,6 +132,7 @@ class CommandTestCaseGenerator
|
||||
if (!$reflection->isInstantiable()) {
|
||||
throw new RuntimeException("Class $class must be instantiable, abstract classes or interfaces are not allowed.");
|
||||
}
|
||||
|
||||
if (!$reflection->implementsInterface('Predis\Command\CommandInterface')) {
|
||||
throw new RuntimeException("Class $class must implement Predis\Command\CommandInterface.");
|
||||
}
|
||||
@@ -173,7 +176,7 @@ class CommandTestCaseGenerator
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
/**
|
||||
* @group commands
|
||||
|
||||
+8
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"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",
|
||||
"license": "MIT",
|
||||
@@ -16,10 +16,10 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
"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",
|
||||
@@ -27,5 +27,10 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"Predis\\": "src/"}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ require __DIR__.'/shared.php';
|
||||
use Predis\Cluster\Distributor\DistributorInterface;
|
||||
use Predis\Cluster\Hash\HashGeneratorInterface;
|
||||
use Predis\Cluster\PredisStrategy;
|
||||
use Predis\Connection\Aggregate\PredisCluster;
|
||||
use Predis\Connection\Cluster\PredisCluster;
|
||||
|
||||
class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
|
||||
{
|
||||
@@ -104,8 +104,8 @@ for ($i = 0; $i < 100; ++$i) {
|
||||
$client->get("key:$i");
|
||||
}
|
||||
|
||||
$server1 = $client->getClientFor('first')->info();
|
||||
$server2 = $client->getClientFor('second')->info();
|
||||
$server1 = $client->on('first')->info();
|
||||
$server2 = $client->on('second')->info();
|
||||
|
||||
if (isset($server1['Keyspace'], $server2['Keyspace'])) {
|
||||
$server1 = $server1['Keyspace'];
|
||||
|
||||
@@ -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]";
|
||||
|
||||
@@ -51,7 +51,7 @@ class EventsListener implements Countable
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
public function __invoke($payload)
|
||||
public function __invoke($payload, $dispatcher)
|
||||
{
|
||||
$this->events[] = $payload;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ class EventsListener implements Countable
|
||||
$dispatcher->attachCallback('events', ($events = new EventsListener()));
|
||||
|
||||
// Attach a function to control the dispatcher loop termination with a message.
|
||||
$dispatcher->attachCallback('control', function ($payload) use ($dispatcher) {
|
||||
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
|
||||
if ($payload === 'terminate_dispatcher') {
|
||||
$dispatcher->stop();
|
||||
}
|
||||
|
||||
@@ -13,11 +13,10 @@ require __DIR__.'/shared.php';
|
||||
|
||||
// This example will not work with versions of Redis < 2.6.
|
||||
//
|
||||
// Additionally to the EVAL command defined in the current development profile,
|
||||
// the Predis\Command\ScriptCommand class can be used to build an higher level
|
||||
// abstraction for "scriptable" commands so that they will appear just like any
|
||||
// other command on the client-side. This is a quick example used to implement
|
||||
// INCREX.
|
||||
// Additionally to the EVAL command, the Predis\Command\ScriptCommand class can
|
||||
// be used to leverage an higher level abstraction for Lua scripting that makes
|
||||
// scripts appear just like any other command on the client-side. This is basic
|
||||
// example on how a script-based INCREX command can be defined:
|
||||
|
||||
use Predis\Command\ScriptCommand;
|
||||
|
||||
@@ -50,12 +49,9 @@ LUA;
|
||||
}
|
||||
|
||||
$client = new Predis\Client($single_server, array(
|
||||
'profile' => function ($options) {
|
||||
$profile = $options->getDefault('profile');
|
||||
$profile->defineCommand('increxby', 'IncrementExistingKeysBy');
|
||||
|
||||
return $profile;
|
||||
},
|
||||
'commands' => array(
|
||||
'increxby' => 'IncrementExistingKeysBy',
|
||||
),
|
||||
));
|
||||
|
||||
$client->mset('foo', 10, 'foobar', 100);
|
||||
|
||||
@@ -13,7 +13,7 @@ require __DIR__.'/shared.php';
|
||||
|
||||
use Predis\Collection\Iterator;
|
||||
|
||||
// Starting from Redis 2.8, clients can iterate incrementally over collections
|
||||
// Starting with Redis 2.8, clients can iterate incrementally over collections
|
||||
// without blocking the server like it happens when a command such as KEYS is
|
||||
// executed on a Redis instance storing millions of keys. These commands are:
|
||||
//
|
||||
@@ -29,8 +29,7 @@ use Predis\Collection\Iterator;
|
||||
// See http://redis.io/commands/scan for more details.
|
||||
//
|
||||
|
||||
// Create a client using `2.8` as a server profile (needs Redis 2.8!)
|
||||
$client = new Predis\Client($single_server, array('profile' => '2.8'));
|
||||
$client = new Predis\Client($single_server);
|
||||
|
||||
// Prepare some keys for our example
|
||||
$client->del('predis:set', 'predis:zset', 'predis:hash');
|
||||
|
||||
@@ -14,12 +14,12 @@ require __DIR__.'/shared.php';
|
||||
// Predis allows to set Lua scripts as read-only operations for replication.
|
||||
// This works for both EVAL and EVALSHA and also for the client-side abstraction
|
||||
// built upon them (Predis\Command\ScriptCommand). This example shows a slightly
|
||||
// more complex configuration that injects a new script command in the server
|
||||
// profile used by the new client instance and marks it marks it as a read-only
|
||||
// operation for replication so that it will be executed on slaves.
|
||||
// more complex configuration that injects a new script command in the command
|
||||
// factory used by the client and marks it as a read-only operation so that it
|
||||
// will be executed on slaves.
|
||||
|
||||
use Predis\Command\ScriptCommand;
|
||||
use Predis\Connection\Aggregate\MasterSlaveReplication;
|
||||
use Predis\Connection\Replication\MasterSlaveReplication;
|
||||
use Predis\Replication\ReplicationStrategy;
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
@@ -52,12 +52,9 @@ $parameters = array(
|
||||
);
|
||||
|
||||
$options = array(
|
||||
'profile' => function ($options, $option) {
|
||||
$profile = $options->getDefault($option);
|
||||
$profile->defineCommand('hmgetall', 'HashMultipleGetAll');
|
||||
|
||||
return $profile;
|
||||
},
|
||||
'commands' => array(
|
||||
'hmgetall' => 'HashMultipleGetAll',
|
||||
),
|
||||
'replication' => function () {
|
||||
$strategy = new ReplicationStrategy();
|
||||
$strategy->setScriptReadOnly(HashMultipleGetAll::BODY);
|
||||
|
||||
@@ -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'.
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ $parameters = array(
|
||||
'tcp://127.0.0.1:6380?database=15&alias=slave',
|
||||
);
|
||||
|
||||
$options = array('replication' => true);
|
||||
$options = array('replication' => 'predis');
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
|
||||
|
||||
+8
-8
@@ -23,22 +23,22 @@ function redis_version($info)
|
||||
}
|
||||
|
||||
$single_server = array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'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.
|
||||
|
||||
+4
-4
@@ -7,17 +7,17 @@
|
||||
|
||||
[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.0.2"
|
||||
stability = "stable"
|
||||
version = "2.0.0"
|
||||
stability = "devel"
|
||||
channel = "pear.nrk.io"
|
||||
|
||||
author = "Daniele Alessandri \"nrk\" <suppakilla@gmail.com>"
|
||||
|
||||
[require]
|
||||
php = ">= 5.3.2"
|
||||
php = ">= 5.3.9"
|
||||
pearinstaller = "1.4.1"
|
||||
|
||||
[roles]
|
||||
|
||||
+10
-5
@@ -1,10 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
beStrictAboutTestSize="true"
|
||||
checkForUnintentionallyCoveredCode="true"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true">
|
||||
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">
|
||||
@@ -32,7 +38,6 @@
|
||||
|
||||
<php>
|
||||
<!-- Redis -->
|
||||
<const name="REDIS_SERVER_VERSION" value="2.8" />
|
||||
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="15" />
|
||||
|
||||
+10
-5
@@ -1,10 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
beStrictAboutTestSize="true"
|
||||
checkForUnintentionallyCoveredCode="true"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true">
|
||||
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">
|
||||
@@ -36,7 +42,6 @@
|
||||
|
||||
<php>
|
||||
<!-- Redis -->
|
||||
<const name="REDIS_SERVER_VERSION" value="2.8" />
|
||||
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="15" />
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Predis;
|
||||
*
|
||||
* @author Eric Naeseth <eric@thumbtack.com>
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
|
||||
+100
-58
@@ -19,6 +19,7 @@ use Predis\Configuration\OptionsInterface;
|
||||
use Predis\Connection\AggregateConnectionInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Connection\ParametersInterface;
|
||||
use Predis\Connection\Replication\SentinelReplication;
|
||||
use Predis\Monitor\Consumer as MonitorConsumer;
|
||||
use Predis\Pipeline\Pipeline;
|
||||
use Predis\PubSub\Consumer as PubSubConsumer;
|
||||
@@ -38,13 +39,24 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class Client implements ClientInterface
|
||||
class Client implements ClientInterface, \IteratorAggregate
|
||||
{
|
||||
const VERSION = '1.0.2';
|
||||
const VERSION = '2.0.0-dev';
|
||||
|
||||
protected $connection;
|
||||
protected $options;
|
||||
private $profile;
|
||||
/**
|
||||
* @var Predis\Configuration\OptionsInterface
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var Predis\Connection\ConnectionInterface
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* @var Predis\Command\FactoryInterface
|
||||
*/
|
||||
private $commands;
|
||||
|
||||
/**
|
||||
* @param mixed $parameters Connection parameters for one or more servers.
|
||||
@@ -54,7 +66,7 @@ class Client implements ClientInterface
|
||||
{
|
||||
$this->options = $this->createOptions($options ?: array());
|
||||
$this->connection = $this->createConnection($parameters ?: array());
|
||||
$this->profile = $this->options->profile;
|
||||
$this->commands = $this->options->commands;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +90,7 @@ class Client implements ClientInterface
|
||||
return $options;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Invalid type for client options.');
|
||||
throw new \InvalidArgumentException('Invalid type for client options');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,76 +114,76 @@ class Client implements ClientInterface
|
||||
*/
|
||||
protected function createConnection($parameters)
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
|
||||
if ($parameters instanceof ConnectionInterface) {
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
if ($parameters instanceof ParametersInterface || is_string($parameters)) {
|
||||
return $this->options->connections->create($parameters);
|
||||
return $options->connections->create($parameters);
|
||||
}
|
||||
|
||||
if (is_array($parameters)) {
|
||||
if (!isset($parameters[0])) {
|
||||
return $this->options->connections->create($parameters);
|
||||
return $options->connections->create($parameters);
|
||||
}
|
||||
|
||||
$options = $this->options;
|
||||
|
||||
if ($options->defined('aggregate')) {
|
||||
$initializer = $this->getConnectionInitializerWrapper($options->aggregate);
|
||||
$connection = $initializer($parameters, $options);
|
||||
if ($options->defined('cluster')) {
|
||||
return $this->createAggregateConnection($parameters, 'cluster');
|
||||
} elseif ($options->defined('replication')) {
|
||||
return $this->createAggregateConnection($parameters, 'replication');
|
||||
} elseif ($options->defined('aggregate')) {
|
||||
return $this->createAggregateConnection($parameters, 'aggregate');
|
||||
} else {
|
||||
if ($options->defined('replication') && $replication = $options->replication) {
|
||||
$connection = $replication;
|
||||
} else {
|
||||
$connection = $options->cluster;
|
||||
}
|
||||
|
||||
$options->connections->aggregate($connection, $parameters);
|
||||
throw new \InvalidArgumentException(
|
||||
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
|
||||
);
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
if (is_callable($parameters)) {
|
||||
$initializer = $this->getConnectionInitializerWrapper($parameters);
|
||||
$connection = $initializer($this->options);
|
||||
$connection = call_user_func($parameters, $options);
|
||||
|
||||
if (!$connection instanceof ConnectionInterface) {
|
||||
throw new \InvalidArgumentException('Callable parameters must return a valid connection');
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Invalid type for connection parameters.');
|
||||
throw new \InvalidArgumentException('Invalid type for connection parameters');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a callable to make sure that its returned value represents a valid
|
||||
* connection type.
|
||||
* Creates an aggregate connection.
|
||||
*
|
||||
* @param mixed $callable
|
||||
* @param mixed $parameters Connection parameters.
|
||||
* @param string $option Option for aggregate connections (`aggregate`, `cluster`, `replication`).
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function getConnectionInitializerWrapper($callable)
|
||||
protected function createAggregateConnection($parameters, $option)
|
||||
{
|
||||
return function () use ($callable) {
|
||||
$connection = call_user_func_array($callable, func_get_args());
|
||||
$options = $this->getOptions();
|
||||
|
||||
if (!$connection instanceof ConnectionInterface) {
|
||||
throw new \UnexpectedValueException(
|
||||
'The callable connection initializer returned an invalid type.'
|
||||
);
|
||||
}
|
||||
$initializer = $options->$option;
|
||||
$connection = $initializer($parameters);
|
||||
|
||||
return $connection;
|
||||
};
|
||||
// TODO: this is dirty but we must skip the redis-sentinel backend for now.
|
||||
if ($option !== 'aggregate' && !$connection instanceof SentinelReplication) {
|
||||
$options->connections->aggregate($connection, $parameters);
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProfile()
|
||||
public function getCommandFactory()
|
||||
{
|
||||
return $this->profile;
|
||||
return $this->commands;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,23 +195,34 @@ class Client implements ClientInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new client instance for the specified connection ID or alias,
|
||||
* only when working with an aggregate connection (cluster, replication).
|
||||
* The new client instances uses the same options of the original one.
|
||||
* Creates a new client from the specified connection ID / alias.
|
||||
*
|
||||
* @param string $connectionID Identifier of a connection.
|
||||
* The new client instances inherites the same options of the original one.
|
||||
* When no callable object is supplied, this method returns the new client.
|
||||
* When a callable object is supplied, the new client is passed as its sole
|
||||
* argument and its return value is returned by this method to the caller.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* NOTE: This method works only when the client is configured to work with
|
||||
* aggregate connections (cluster, replication).
|
||||
*
|
||||
* @return Client
|
||||
* @param string $connectionID Identifier of a connection.
|
||||
* @param callable|null $callable Optional callable object.
|
||||
*
|
||||
* @return ClientInterface|mixed
|
||||
*/
|
||||
public function getClientFor($connectionID)
|
||||
public function on($connectionID, $callable = null)
|
||||
{
|
||||
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);
|
||||
$client = new static($connection, $this->getOptions());
|
||||
|
||||
if ($callable) {
|
||||
return call_user_func($callable, $client);
|
||||
} else {
|
||||
return $client;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,7 +296,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.
|
||||
@@ -284,9 +307,10 @@ class Client implements ClientInterface
|
||||
public function executeRaw(array $arguments, &$error = null)
|
||||
{
|
||||
$error = false;
|
||||
$commandID = array_shift($arguments);
|
||||
|
||||
$response = $this->connection->executeCommand(
|
||||
new RawCommand($arguments)
|
||||
new RawCommand($commandID, $arguments)
|
||||
);
|
||||
|
||||
if ($response instanceof ResponseInterface) {
|
||||
@@ -315,7 +339,7 @@ class Client implements ClientInterface
|
||||
*/
|
||||
public function createCommand($commandID, $arguments = array())
|
||||
{
|
||||
return $this->profile->createCommand($commandID, $arguments);
|
||||
return $this->commands->createCommand($commandID, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,10 +373,7 @@ class Client implements ClientInterface
|
||||
protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response)
|
||||
{
|
||||
if ($command instanceof ScriptCommand && $response->getErrorType() === 'NOSCRIPT') {
|
||||
$eval = $this->createCommand('EVAL');
|
||||
$eval->setRawArguments($command->getEvalArguments());
|
||||
|
||||
$response = $this->executeCommand($eval);
|
||||
$response = $this->executeCommand($command->getEvalCommand());
|
||||
|
||||
if (!$response instanceof ResponseInterface) {
|
||||
$response = $command->parseResponse($response);
|
||||
@@ -395,9 +416,11 @@ class Client implements ClientInterface
|
||||
|
||||
return $this->$initializer($arg0, $arg1);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
default:
|
||||
return $this->$initializer($this, $argv);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -476,7 +499,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.
|
||||
@@ -520,4 +543,23 @@ class Client implements ClientInterface
|
||||
{
|
||||
return new MonitorConsumer($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
$clients = array();
|
||||
$connection = $this->getConnection();
|
||||
|
||||
if (!$connection instanceof \Traversable) {
|
||||
throw new ClientException('The underlying connection is not traversable');
|
||||
}
|
||||
|
||||
foreach ($connection as $node) {
|
||||
$clients[(string) $node] = new static($node, $this->getOptions());
|
||||
}
|
||||
|
||||
return new \ArrayIterator($clients);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ 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, ...)
|
||||
* @method $this decr($key)
|
||||
* @method $this decrby($key, $decrement)
|
||||
* @method $this get($key)
|
||||
@@ -71,6 +72,7 @@ use Predis\Command\CommandInterface;
|
||||
* @method $this hset($key, $field, $value)
|
||||
* @method $this hsetnx($key, $field, $value)
|
||||
* @method $this hvals($key)
|
||||
* @method $this hstrlen($key, $field)
|
||||
* @method $this blpop(array $keys, $timeout)
|
||||
* @method $this brpop(array $keys, $timeout)
|
||||
* @method $this brpoplpush($source, $destination, $timeout)
|
||||
@@ -97,7 +99,7 @@ use Predis\Command\CommandInterface;
|
||||
* @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)
|
||||
@@ -121,6 +123,7 @@ use Predis\Command\CommandInterface;
|
||||
* @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)
|
||||
@@ -154,6 +157,12 @@ 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>
|
||||
*/
|
||||
|
||||
+15
-6
@@ -12,9 +12,9 @@
|
||||
namespace Predis;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\FactoryInterface;
|
||||
use Predis\Configuration\OptionsInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Profile\ProfileInterface;
|
||||
|
||||
/**
|
||||
* Interface defining a client able to execute commands against Redis.
|
||||
@@ -46,6 +46,7 @@ use Predis\Profile\ProfileInterface;
|
||||
* @method int append($key, $value)
|
||||
* @method int bitcount($key, $start = null, $end = null)
|
||||
* @method int bitop($operation, $destkey, $key)
|
||||
* @method array bitfield($key, ...)
|
||||
* @method int decr($key)
|
||||
* @method int decrby($key, $decrement)
|
||||
* @method string get($key)
|
||||
@@ -79,6 +80,7 @@ use Predis\Profile\ProfileInterface;
|
||||
* @method int hset($key, $field, $value)
|
||||
* @method int hsetnx($key, $field, $value)
|
||||
* @method array hvals($key)
|
||||
* @method int hstrlen($key, $field)
|
||||
* @method array blpop(array $keys, $timeout)
|
||||
* @method array brpop(array $keys, $timeout)
|
||||
* @method array brpoplpush($source, $destination, $timeout)
|
||||
@@ -105,7 +107,7 @@ use Predis\Profile\ProfileInterface;
|
||||
* @method int sismember($key, $member)
|
||||
* @method array smembers($key)
|
||||
* @method int smove($source, $destination, $member)
|
||||
* @method string spop($key)
|
||||
* @method string spop($key, $count = null)
|
||||
* @method string srandmember($key, $count = null)
|
||||
* @method int srem($key, $member)
|
||||
* @method array sscan($key, $cursor, array $options = null)
|
||||
@@ -123,12 +125,13 @@ use Predis\Profile\ProfileInterface;
|
||||
* @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 array zrevrangebyscore($key, $max, $min, 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 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)
|
||||
@@ -162,17 +165,23 @@ use Predis\Profile\ProfileInterface;
|
||||
* @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 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>
|
||||
*/
|
||||
interface ClientInterface
|
||||
{
|
||||
/**
|
||||
* Returns the server profile used by the client.
|
||||
* Returns the command factory used by the client.
|
||||
*
|
||||
* @return ProfileInterface
|
||||
* @return FactoryInterface
|
||||
*/
|
||||
public function getProfile();
|
||||
public function getCommandFactory();
|
||||
|
||||
/**
|
||||
* Returns the client options specified upon initialization.
|
||||
|
||||
@@ -43,7 +43,7 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
|
||||
return array(
|
||||
/* commands operating on the key space */
|
||||
'EXISTS' => $getKeyFromFirstArgument,
|
||||
'EXISTS' => $getKeyFromAllArguments,
|
||||
'DEL' => $getKeyFromAllArguments,
|
||||
'TYPE' => $getKeyFromFirstArgument,
|
||||
'EXPIRE' => $getKeyFromFirstArgument,
|
||||
@@ -53,7 +53,7 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
'PEXPIREAT' => $getKeyFromFirstArgument,
|
||||
'TTL' => $getKeyFromFirstArgument,
|
||||
'PTTL' => $getKeyFromFirstArgument,
|
||||
'SORT' => $getKeyFromFirstArgument, // TODO
|
||||
'SORT' => array($this, 'getKeyFromSortCommand'),
|
||||
'DUMP' => $getKeyFromFirstArgument,
|
||||
'RESTORE' => $getKeyFromFirstArgument,
|
||||
|
||||
@@ -80,6 +80,7 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
'SUBSTR' => $getKeyFromFirstArgument,
|
||||
'BITOP' => array($this, 'getKeyFromBitOp'),
|
||||
'BITCOUNT' => $getKeyFromFirstArgument,
|
||||
'BITFIELD' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on lists */
|
||||
'LINSERT' => $getKeyFromFirstArgument,
|
||||
@@ -164,6 +165,14 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
/* scripting */
|
||||
'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'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -65,8 +65,8 @@ abstract class CursorBasedIterator implements \Iterator
|
||||
*/
|
||||
protected function requiredCommand(ClientInterface $client, $commandID)
|
||||
{
|
||||
if (!$client->getProfile()->supportsCommand($commandID)) {
|
||||
throw new NotSupportedException("The current profile does not support '$commandID'.");
|
||||
if (!$client->getCommandFactory()->supportsCommand($commandID)) {
|
||||
throw new NotSupportedException("'$commandID' is not supported by the current command factory.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,11 @@ class HashKey extends CursorBasedIterator
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position = key($this->elements);
|
||||
$this->current = array_shift($this->elements);
|
||||
if ($kv = each($this->elements)) {
|
||||
$this->position = $kv[0];
|
||||
$this->current = $kv[1];
|
||||
|
||||
unset($this->elements[$this->position]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ class ListKey implements \Iterator
|
||||
*/
|
||||
protected function requiredCommand(ClientInterface $client, $commandID)
|
||||
{
|
||||
if (!$client->getProfile()->supportsCommand($commandID)) {
|
||||
throw new NotSupportedException("The current profile does not support '$commandID'.");
|
||||
if (!$client->getCommandFactory()->supportsCommand($commandID)) {
|
||||
throw new NotSupportedException("'$commandID' is not supported by the current command factory.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-13
@@ -21,24 +21,12 @@ abstract class Command implements CommandInterface
|
||||
private $slot;
|
||||
private $arguments = array();
|
||||
|
||||
/**
|
||||
* Returns a filtered array of the arguments.
|
||||
*
|
||||
* @param array $arguments List of arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
{
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $this->filterArguments($arguments);
|
||||
$this->arguments = $arguments;
|
||||
unset($this->slot);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,43 +9,30 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Profile;
|
||||
namespace Predis\Command;
|
||||
|
||||
use Predis\ClientException;
|
||||
use Predis\Command\Processor\ProcessorInterface;
|
||||
|
||||
/**
|
||||
* Base class implementing common functionalities for Redis server profiles.
|
||||
* Base command factory.
|
||||
*
|
||||
* This class provides all of the common functionalities needed for the creation
|
||||
* of new instances of Redis commands.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class RedisProfile implements ProfileInterface
|
||||
abstract class Factory implements FactoryInterface
|
||||
{
|
||||
private $commands;
|
||||
private $processor;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->commands = $this->getSupportedCommands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of all the commands supported by the profile and their
|
||||
* actual PHP classes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getSupportedCommands();
|
||||
protected $commands = array();
|
||||
protected $processor;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsCommand($commandID)
|
||||
{
|
||||
return isset($this->commands[strtoupper($commandID)]);
|
||||
return $this->getCommandClass($commandID) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +50,9 @@ abstract class RedisProfile implements ProfileInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified name of a class representing the specified
|
||||
* command ID registered in the current server profile.
|
||||
* Returns the FQN of a class that represents the specified command ID.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $commandID Command ID.
|
||||
*
|
||||
@@ -82,13 +70,12 @@ abstract class RedisProfile implements ProfileInterface
|
||||
*/
|
||||
public function createCommand($commandID, array $arguments = array())
|
||||
{
|
||||
$commandID = strtoupper($commandID);
|
||||
if (!$commandClass = $this->getCommandClass($commandID)) {
|
||||
$commandID = strtoupper($commandID);
|
||||
|
||||
if (!isset($this->commands[$commandID])) {
|
||||
throw new ClientException("Command '$commandID' is not a registered Redis command.");
|
||||
}
|
||||
|
||||
$commandClass = $this->commands[$commandID];
|
||||
$command = new $commandClass();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
@@ -100,7 +87,7 @@ abstract class RedisProfile implements ProfileInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a new command in the server profile.
|
||||
* Defines a new command in the factory.
|
||||
*
|
||||
* @param string $commandID Command ID.
|
||||
* @param string $class Fully-qualified name of a Predis\Command\CommandInterface.
|
||||
@@ -109,10 +96,12 @@ abstract class RedisProfile implements ProfileInterface
|
||||
*/
|
||||
public function defineCommand($commandID, $class)
|
||||
{
|
||||
$reflection = new \ReflectionClass($class);
|
||||
if ($class !== null) {
|
||||
$reflection = new \ReflectionClass($class);
|
||||
|
||||
if (!$reflection->isSubclassOf('Predis\Command\CommandInterface')) {
|
||||
throw new \InvalidArgumentException("The class '$class' is not a valid command class.");
|
||||
if (!$reflection->isSubclassOf('Predis\Command\CommandInterface')) {
|
||||
throw new \InvalidArgumentException("The class '$class' is not a valid command class.");
|
||||
}
|
||||
}
|
||||
|
||||
$this->commands[strtoupper($commandID)] = $class;
|
||||
@@ -133,14 +122,4 @@ abstract class RedisProfile implements ProfileInterface
|
||||
{
|
||||
return $this->processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of server profile as its string representation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getVersion();
|
||||
}
|
||||
}
|
||||
@@ -9,28 +9,20 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Profile;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
namespace Predis\Command;
|
||||
|
||||
/**
|
||||
* A profile defines all the features and commands supported by certain versions
|
||||
* of Redis. Instances of Predis\Client should use a server profile matching the
|
||||
* version of Redis being used.
|
||||
* Command factory interface.
|
||||
*
|
||||
* Each Redis command should have a class counterpart and commands factories are
|
||||
* used to create new instances of these classes through the library.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface ProfileInterface
|
||||
interface FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Returns the profile version corresponding to the Redis version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVersion();
|
||||
|
||||
/**
|
||||
* Checks if the profile supports the specified command.
|
||||
* Checks if the command factory supports the specified command.
|
||||
*
|
||||
* @param string $commandID Command ID.
|
||||
*
|
||||
@@ -39,7 +31,7 @@ interface ProfileInterface
|
||||
public function supportsCommand($commandID);
|
||||
|
||||
/**
|
||||
* Checks if the profile supports the specified list of commands.
|
||||
* Checks if the command factory supports the specified list of commands.
|
||||
*
|
||||
* @param array $commandIDs List of command IDs.
|
||||
*
|
||||
@@ -33,7 +33,7 @@ class KeyPrefixProcessor implements ProcessorInterface
|
||||
$this->prefix = $prefix;
|
||||
$this->commands = array(
|
||||
/* ---------------- Redis 1.2 ---------------- */
|
||||
'EXISTS' => 'static::first',
|
||||
'EXISTS' => 'static::all',
|
||||
'DEL' => 'static::all',
|
||||
'TYPE' => 'static::first',
|
||||
'KEYS' => 'static::first',
|
||||
@@ -159,6 +159,13 @@ class KeyPrefixProcessor implements ProcessorInterface
|
||||
'BITPOS' => 'static::first',
|
||||
/* ---------------- Redis 3.2 ---------------- */
|
||||
'HSTRLEN' => 'static::first',
|
||||
'BITFIELD' => 'static::first',
|
||||
'GEOADD' => 'static::first',
|
||||
'GEOHASH' => 'static::first',
|
||||
'GEOPOS' => 'static::first',
|
||||
'GEODIST' => 'static::first',
|
||||
'GEORADIUS' => 'static::georadius',
|
||||
'GEORADIUSBYMEMBER' => 'static::georadius',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -338,7 +345,7 @@ class KeyPrefixProcessor implements ProcessorInterface
|
||||
|
||||
if (($count = count($arguments)) > 1) {
|
||||
for ($i = 1; $i < $count; ++$i) {
|
||||
switch ($arguments[$i]) {
|
||||
switch (strtoupper($arguments[$i])) {
|
||||
case 'BY':
|
||||
case 'STORE':
|
||||
$arguments[$i] = "$prefix{$arguments[++$i]}";
|
||||
@@ -412,4 +419,32 @@ class KeyPrefixProcessor implements ProcessorInterface
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to the key of a GEORADIUS command.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function georadius(CommandInterface $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
|
||||
|
||||
if (($count = count($arguments)) > $startIndex) {
|
||||
for ($i = $startIndex; $i < $count; ++$i) {
|
||||
switch (strtoupper($arguments[$i])) {
|
||||
case 'STORE':
|
||||
case 'STOREDIST':
|
||||
$arguments[$i] = "$prefix{$arguments[++$i]}";
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +111,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
|
||||
{
|
||||
if (!$processor instanceof ProcessorInterface) {
|
||||
throw new \InvalidArgumentException(
|
||||
'A processor chain accepts only instances of '.
|
||||
"'Predis\Command\Processor\ProcessorInterface'."
|
||||
'Processor chain accepts only instances of `Predis\Command\Processor\ProcessorInterface`'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,20 +28,13 @@ class RawCommand implements CommandInterface
|
||||
private $arguments;
|
||||
|
||||
/**
|
||||
* @param array $arguments Command ID and its arguments.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @param string $commandID Command ID.
|
||||
* @param array $arguments Command arguments.
|
||||
*/
|
||||
public function __construct(array $arguments)
|
||||
public function __construct($commandID, array $arguments = array())
|
||||
{
|
||||
if (!$arguments) {
|
||||
throw new \InvalidArgumentException(
|
||||
'The arguments array must contain at least the command ID.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->commandID = strtoupper(array_shift($arguments));
|
||||
$this->arguments = $arguments;
|
||||
$this->commandID = strtoupper($commandID);
|
||||
$this->setArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +48,7 @@ class RawCommand implements CommandInterface
|
||||
public static function create($commandID /* [ $arg, ... */)
|
||||
{
|
||||
$arguments = func_get_args();
|
||||
$command = new self($arguments);
|
||||
$command = new static(array_shift($arguments), $arguments);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/append
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringAppend extends Command
|
||||
class APPEND extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/auth
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionAuth extends Command
|
||||
class AUTH extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bgrewriteaof
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerBackgroundRewriteAOF extends Command
|
||||
class BGREWRITEAOF extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bgsave
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerBackgroundSave extends Command
|
||||
class BGSAVE extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bitcount
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringBitCount extends Command
|
||||
class BITCOUNT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bitfield
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class BITFIELD extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BITFIELD';
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bitop
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringBitOp extends Command
|
||||
class BITOP extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,7 +31,7 @@ class StringBitOp extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 3 && is_array($arguments[2])) {
|
||||
list($operation, $destination) = $arguments;
|
||||
@@ -37,6 +39,6 @@ class StringBitOp extends Command
|
||||
array_unshift($arguments, $operation, $destination);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/bitpos
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringBitPos extends Command
|
||||
class BITPOS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/blpop
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopFirstBlocking extends Command
|
||||
class BLPOP extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,13 +31,13 @@ class ListPopFirstBlocking extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[0])) {
|
||||
list($arguments, $timeout) = $arguments;
|
||||
array_push($arguments, $timeout);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/brpop
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopLastBlocking extends ListPopFirstBlocking
|
||||
class BRPOP extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,4 +27,17 @@ class ListPopLastBlocking extends ListPopFirstBlocking
|
||||
{
|
||||
return 'BRPOP';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[0])) {
|
||||
list($arguments, $timeout) = $arguments;
|
||||
array_push($arguments, $timeout);
|
||||
}
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/brpoplpush
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopLastPushHeadBlocking extends Command
|
||||
class BRPOPLPUSH extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,7 +9,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/client-list
|
||||
@@ -19,7 +21,7 @@ namespace Predis\Command;
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerClient extends Command
|
||||
class CLIENT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -44,7 +46,7 @@ class ServerClient extends Command
|
||||
case 'SETNAME':
|
||||
default:
|
||||
return $data;
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as BaseCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/command
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerCommand extends Command
|
||||
class COMMAND extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,7 +9,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/config-set
|
||||
@@ -19,7 +21,7 @@ namespace Predis\Command;
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerConfig extends Command
|
||||
class CONFIG extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/dbsize
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerDatabaseSize extends Command
|
||||
class DBSIZE extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/decr
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringDecrement extends Command
|
||||
class DECR extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/decrby
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringDecrementBy extends Command
|
||||
class DECRBY extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/del
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyDelete extends Command
|
||||
class DEL extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,8 +31,10 @@ class KeyDelete extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
return self::normalizeArguments($arguments);
|
||||
$arguments = self::normalizeArguments($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/discard
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class TransactionDiscard extends Command
|
||||
class DISCARD extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/dump
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyDump extends Command
|
||||
class DUMP extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/echo
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionEcho extends Command
|
||||
class ECHO_ extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,14 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/evalsha
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerEvalSHA extends ServerEval
|
||||
class EVALSHA extends EVAL_
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/eval
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerEval extends Command
|
||||
class EVAL_ extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/exec
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class TransactionExec extends Command
|
||||
class EXEC extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/exists
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExists extends Command
|
||||
class EXISTS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,12 +27,4 @@ class KeyExists extends Command
|
||||
{
|
||||
return 'EXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/expire
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExpire extends Command
|
||||
class EXPIRE extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,12 +27,4 @@ class KeyExpire extends Command
|
||||
{
|
||||
return 'EXPIRE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/expireat
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExpireAt extends Command
|
||||
class EXPIREAT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,12 +27,4 @@ class KeyExpireAt extends Command
|
||||
{
|
||||
return 'EXPIREAT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/flushall
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerFlushAll extends Command
|
||||
class FLUSHALL extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/flushdb
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerFlushDatabase extends Command
|
||||
class FLUSHDB extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geoadd
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GEOADD extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOADD';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
foreach (array_pop($arguments) as $item) {
|
||||
$arguments = array_merge($arguments, $item);
|
||||
}
|
||||
}
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geodist
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GEODIST extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEODIST';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geohash
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GEOHASH extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOHASH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
$members = array_pop($arguments);
|
||||
$arguments = array_merge($arguments, $members);
|
||||
}
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/geopos
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GEOPOS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOPOS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
$members = array_pop($arguments);
|
||||
$arguments = array_merge($arguments, $members);
|
||||
}
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?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\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/georadius
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GEORADIUS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEORADIUS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(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'];
|
||||
}
|
||||
}
|
||||
|
||||
parent::setArguments($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\Redis;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/georadiusbymember
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class GEORADIUSBYMEMBER extends GEORADIUS
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'GEORADIUSBYMEMBER';
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/get
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringGet extends Command
|
||||
class GET extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/getbit
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringGetBit extends Command
|
||||
class GETBIT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/getrange
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringGetRange extends Command
|
||||
class GETRANGE extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/getset
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringGetSet extends Command
|
||||
class GETSET extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hdel
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashDelete extends Command
|
||||
class HDEL extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,8 +31,10 @@ class HashDelete extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
return self::normalizeVariadic($arguments);
|
||||
$arguments = self::normalizeVariadic($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hexists
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashExists extends Command
|
||||
class HEXISTS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,12 +27,4 @@ class HashExists extends Command
|
||||
{
|
||||
return 'HEXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hget
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGet extends Command
|
||||
class HGET extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hgetall
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGetAll extends Command
|
||||
class HGETALL extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hincrby
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashIncrementBy extends Command
|
||||
class HINCRBY extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hincrbyfloat
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashIncrementByFloat extends Command
|
||||
class HINCRBYFLOAT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hkeys
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashKeys extends Command
|
||||
class HKEYS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hlen
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashLength extends Command
|
||||
class HLEN extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hmget
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGetMultiple extends Command
|
||||
class HMGET extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,8 +31,10 @@ class HashGetMultiple extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
return self::normalizeVariadic($arguments);
|
||||
$arguments = self::normalizeVariadic($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hmset
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSetMultiple extends Command
|
||||
class HMSET extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,7 +31,7 @@ class HashSetMultiple extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
$flattenedKVs = array($arguments[0]);
|
||||
@@ -40,9 +42,9 @@ class HashSetMultiple extends Command
|
||||
$flattenedKVs[] = $v;
|
||||
}
|
||||
|
||||
return $flattenedKVs;
|
||||
$arguments = $flattenedKVs;
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hscan
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashScan extends Command
|
||||
class HSCAN extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -29,14 +31,14 @@ class HashScan extends Command
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(array $arguments)
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (count($arguments) === 3 && is_array($arguments[2])) {
|
||||
$options = $this->prepareOptions(array_pop($arguments));
|
||||
$arguments = array_merge($arguments, $options);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hset
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSet extends Command
|
||||
class HSET extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,12 +27,4 @@ class HashSet extends Command
|
||||
{
|
||||
return 'HSET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hsetnx
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSetPreserve extends Command
|
||||
class HSETNX extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,12 +27,4 @@ class HashSetPreserve extends Command
|
||||
{
|
||||
return 'HSETNX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hstrlen
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashStringLength extends Command
|
||||
class HSTRLEN extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hvals
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashValues extends Command
|
||||
class HVALS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/incr
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringIncrement extends Command
|
||||
class INCR extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/incrby
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringIncrementBy extends Command
|
||||
class INCRBY extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/incrbyfloat
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class StringIncrementByFloat extends Command
|
||||
class INCRBYFLOAT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/info
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerInfo extends Command
|
||||
class INFO extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -31,10 +33,51 @@ class ServerInfo extends Command
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
$info = array();
|
||||
$infoLines = preg_split('/\r?\n/', $data);
|
||||
if (empty($data) || !$lines = preg_split('/\r?\n/', $data)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach ($infoLines as $row) {
|
||||
if (strpos($lines[0], '#') === 0) {
|
||||
return $this->parseNewResponseFormat($lines);
|
||||
} else {
|
||||
return $this->parseOldResponseFormat($lines);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseNewResponseFormat($lines)
|
||||
{
|
||||
$info = array();
|
||||
$current = null;
|
||||
|
||||
foreach ($lines as $row) {
|
||||
if ($row === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/^# (\w+)$/', $row, $matches)) {
|
||||
$info[$matches[1]] = array();
|
||||
$current = &$info[$matches[1]];
|
||||
continue;
|
||||
}
|
||||
|
||||
list($k, $v) = $this->parseRow($row);
|
||||
$current[$k] = $v;
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseOldResponseFormat($lines)
|
||||
{
|
||||
$info = array();
|
||||
|
||||
foreach ($lines as $row) {
|
||||
if (strpos($row, ':') === false) {
|
||||
continue;
|
||||
}
|
||||
@@ -82,30 +125,4 @@ class ServerInfo extends Command
|
||||
|
||||
return $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the response and extracts the allocation statistics.
|
||||
*
|
||||
* @param string $str Response buffer.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseAllocationStats($str)
|
||||
{
|
||||
$stats = array();
|
||||
|
||||
foreach (explode(',', $str) as $kv) {
|
||||
@list($size, $objects, $extra) = explode('=', $kv);
|
||||
|
||||
// hack to prevent incorrect values when parsing the >=256 key
|
||||
if (isset($extra)) {
|
||||
$size = ">=$objects";
|
||||
$objects = $extra;
|
||||
}
|
||||
|
||||
$stats[$size] = $objects;
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/keys
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyKeys extends Command
|
||||
class KEYS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lastsave
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerLastSave extends Command
|
||||
class LASTSAVE extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lindex
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListIndex extends Command
|
||||
class LINDEX extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/linsert
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListInsert extends Command
|
||||
class LINSERT extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/llen
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListLength extends Command
|
||||
class LLEN extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lpop
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopFirst extends Command
|
||||
class LPOP extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -9,14 +9,16 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command;
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lpush
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPushHead extends ListPushTail
|
||||
class LPUSH extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,4 +27,14 @@ class ListPushHead extends ListPushTail
|
||||
{
|
||||
return 'LPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$arguments = self::normalizeVariadic($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user