mirror of
https://github.com/predis/predis.git
synced 2026-08-19 01:51:40 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f058cb5ea | |||
| f2ab80e7e9 | |||
| ddb5109805 | |||
| ccb48a1857 | |||
| 2fc80a5f0d | |||
| 49e151a3d0 | |||
| 7d181160a3 | |||
| c546351e1d | |||
| 6ca4087118 | |||
| 654b11ba6d | |||
| cf758f23d4 | |||
| 7806614041 | |||
| 852959cbd1 | |||
| 3ebdf16d1c | |||
| 35142cfbcf | |||
| 0f1d4675cf | |||
| 465bd45147 | |||
| 3bfe3897a7 | |||
| 0f966af8e3 | |||
| e3e0475826 | |||
| 767c488d35 | |||
| 1205026fb1 | |||
| 9c314c5b5f | |||
| d05a62e82c | |||
| 6769e0de56 |
@@ -1,5 +0,0 @@
|
||||
*.tgz
|
||||
*.phar
|
||||
phpunit.xml
|
||||
package.xml
|
||||
experiments/
|
||||
@@ -1,9 +0,0 @@
|
||||
language: php
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- v0.7
|
||||
script: phpunit -c phpunit.xml.travisci
|
||||
@@ -0,0 +1,196 @@
|
||||
v0.6.3 (2011-01-01)
|
||||
* New commands available in the Redis v2.2 profile (dev):
|
||||
- Strings: SETRANGE, GETRANGE, SETBIT, GETBIT
|
||||
- Lists : BRPOPLPUSH
|
||||
|
||||
* The abstraction for MULTI/EXEC transactions has been dramatically improved
|
||||
by providing support for check-and-set (CAS) operations when using Redis >=
|
||||
2.2. Aborted transactions can also be optionally replayed in automatic up
|
||||
to a user-defined number of times, after which a Predis_AbortedMultiExec
|
||||
exception is thrown.
|
||||
|
||||
v0.6.2 (2010-11-28)
|
||||
* Minor internal improvements and clean ups.
|
||||
|
||||
* New commands available in the Redis v2.2 profile (dev):
|
||||
- Strings: STRLEN
|
||||
- Lists : LINSERT, RPUSHX, LPUSHX
|
||||
- ZSets : ZREVRANGEBYSCORE
|
||||
- Misc. : PERSIST
|
||||
|
||||
* WATCH also accepts a single array parameter with the keys that should be
|
||||
monitored during a transaction.
|
||||
|
||||
* Improved the behaviour of Predis_MultiExecBlock in certain corner cases.
|
||||
|
||||
* Improved parameters checking for the SORT command.
|
||||
|
||||
* FIX: the STORE parameter for the SORT command didn't work correctly when
|
||||
using '0' as the target key (ISSUE #13).
|
||||
|
||||
* FIX: the methods for UNWATCH and DISCARD do not break anymore method
|
||||
chaining with Predis\MultiExecBlock.
|
||||
|
||||
v0.6.1 (2010-07-11)
|
||||
* Minor internal improvements and clean ups.
|
||||
|
||||
* New commands available in the Redis v2.2 profile (dev):
|
||||
- Misc. : WATCH, UNWATCH
|
||||
|
||||
* Optional modifiers for ZRANGE, ZREVRANGE and ZRANGEBYSCORE queries are
|
||||
supported using an associative array passed as the last argument of their
|
||||
respective methods.
|
||||
|
||||
* The LIMIT modifier for ZRANGEBYSCORE can be specified using either:
|
||||
- an indexed array: array($offset, $count)
|
||||
- an associative array: array('offset' => $offset, 'count' => $count)
|
||||
|
||||
* The method Predis_Client::__construct() now accepts also instances of
|
||||
Predis_ConnectionParameters.
|
||||
|
||||
* Predis_MultiExecBlock and Predis_PubSubContext now throw an exception
|
||||
when trying to create their instances using a profile that does not
|
||||
support the required Redis commands or when the client is connected to
|
||||
a cluster of connections.
|
||||
|
||||
* Various improvements to Predis_MultiExecBlock:
|
||||
- fixes and more consistent behaviour across various usage cases.
|
||||
- support for WATCH and UNWATCH when using the current development
|
||||
profile (Redis v2.2) and aborted transactions.
|
||||
|
||||
* New signature for Predis_Client::multiExec() which is now able to accept
|
||||
an array of options for the underlying instance of Predis_MultiExecBlock.
|
||||
Backwards compatibility with previous releases of Predis is ensured.
|
||||
|
||||
* New signature for Predis_Client::pipeline() which is now able to accept
|
||||
an array of options for the underlying instance of Predis_CommandPipeline.
|
||||
Backwards compatibility with previous releases of Predis is ensured.
|
||||
The method Predis_Client::pipelineSafe() is to be considered deprecated.
|
||||
|
||||
* FIX: The WEIGHT modifier for ZUNIONSTORE and ZINTERSTORE was handled
|
||||
incorrectly with more than two weights specified.
|
||||
|
||||
v0.6.0 (2010-05-24)
|
||||
* Switched to the new multi-bulk request protocol for all of the commands
|
||||
in the Redis 1.2 and Redis 2.0 profiles. Inline and bulk requests are now
|
||||
deprecated as they will be removed in future releases of Redis.
|
||||
|
||||
* The default server profile is "2.0" (targeting Redis 2.0.x). If you are
|
||||
using older versions of Redis, it is highly recommended that you specify
|
||||
which server profile the client should use (e.g. "1.2" when connecting
|
||||
to instances of Redis 1.2.x).
|
||||
|
||||
* Support for Redis 1.0 is now optional and it is provided by requiring
|
||||
'Predis_Compatibility.php' before creating an instance of Predis_Client.
|
||||
|
||||
* New commands added to the Redis 2.0 profile since Predis 0.5.1:
|
||||
- Strings: SETEX, APPEND, SUBSTR
|
||||
- ZSets : ZCOUNT, ZRANK, ZUNIONSTORE, ZINTERSTORE, ZREMBYRANK, ZREVRANK
|
||||
- Hashes : HSET, HSETNX, HMSET, HINCRBY, HGET, HMGET, HDEL, HEXISTS,
|
||||
HLEN, HKEYS, HVALS, HGETALL
|
||||
- PubSub : PUBLISH, SUBSCRIBE, UNSUBSCRIBE
|
||||
- Misc. : DISCARD, CONFIG
|
||||
|
||||
* Introduced client-level options with the new Predis_ClientOptions class.
|
||||
Options can be passed to Predis_Client::__construct in its second argument
|
||||
as an array or an instance of Predis_ClientOptions. For brevity's sake and
|
||||
compatibility with older versions, the constructor of Predis_Client still
|
||||
accepts an instance of Predis_RedisServerProfile in its second argument.
|
||||
The currently supported client options are:
|
||||
- profile [default: "2.0" as of Predis 0.6.0]
|
||||
specifies which server profile to use when connecting to Redis. This
|
||||
option accepts an instance of Predis_RedisServerProfile or a string
|
||||
that indicates the target version.
|
||||
- key_distribution [default: Predis_Distribution_HashRing]
|
||||
specifies which key distribution strategy to use to distribute keys
|
||||
among the servers that compose a cluster. This option accepts an
|
||||
instance of Predis_Distribution_IDistributionStrategy so that users
|
||||
can implement their own key distribution strategy. Optionally, the new
|
||||
Predis_Distribution_KetamaPureRing class also provides a pure-PHP
|
||||
implementation of the same algorithm used by libketama.
|
||||
- throw_on_error [default: TRUE]
|
||||
server errors can optionally be handled "silently": instead of throwing
|
||||
an exception, the client returns an error response type.
|
||||
- iterable_multibulk [EXPERIMENTAL - default: FALSE]
|
||||
in addition to the classic way of fetching a whole multibulk reply
|
||||
into an array, the client can now optionally stream a multibulk reply
|
||||
down to the user code by using PHP iterators. It is just a little bit
|
||||
slower, but it can save a lot of memory in certain scenarios.
|
||||
|
||||
* New parameters for connections:
|
||||
- alias [default: not set]
|
||||
every connection can now be identified by an alias that is useful to
|
||||
get a certain connection when connected to a cluster of Redis servers.
|
||||
- weight [default: not set]
|
||||
allows the client to balance the keys asymmetrically across multiple
|
||||
servers. This might be useful when you have servers with different
|
||||
amounts of memory and you want to distribute the load of your keys
|
||||
accordingly.
|
||||
- connection_async [default: FALSE]
|
||||
estabilish connections to servers in a non-blocking way, so that the
|
||||
client is not blocked while the underlying resource performs the actual
|
||||
connection.
|
||||
- connection_persistent [default: FALSE]
|
||||
the underlying connection resource is left open when a script ends its
|
||||
lifecycle. Persistent connections can lead to unpredictable or strange
|
||||
behaviours, so they should be used with extreme care.
|
||||
|
||||
* Introduced the Predis_Pipeline_IPipelineExecutor interface. Classes that
|
||||
implements this interface are used internally by the Predis_CommandPipeline
|
||||
class to change the behaviour of the pipeline when writing/reading commands
|
||||
from one or multiple servers. Here is the list of the default executors:
|
||||
- Predis_Pipeline_StandardExecutor
|
||||
Exceptions generated by server errors might be thrown depending on the
|
||||
options passed to the client (see "throw_on_error"). Instead, protocol
|
||||
or network errors always throw exceptions. This is the default executor
|
||||
for single and clustered connections and shares the same behaviour of
|
||||
Predis 0.5.x.
|
||||
- Predis_Pipeline_SafeExecutor
|
||||
Exceptions generated by server, protocol or network errors are not
|
||||
thrown, instead they are returned in the response array as instances of
|
||||
ResponseError or CommunicationException.
|
||||
- Predis_Pipeline_SafeClusterExecutor
|
||||
This executor shares the same behaviour of Predis_Pipeline_SafeExecutor
|
||||
but it is geared towards clustered connections.
|
||||
|
||||
* Support for PUBSUB is handled by the new Predis_PubSubContext class, which
|
||||
could also be used to build a callback dispatcher for PUBSUB scenarios.
|
||||
|
||||
* When connected to a cluster of connections, it is now possible to get a
|
||||
new Predis_Client instance for a single connection of the cluster by
|
||||
passing its alias/index to the new Predis_Client::getClientFor() method.
|
||||
|
||||
* CommandPipeline and MultiExecBlock return their instances when invoking
|
||||
commands, thus allowing method chaining in pipelines and multi-exec blocks.
|
||||
|
||||
* MultiExecBlock instances can handle the new DISCARD command.
|
||||
|
||||
* Connections now support float values for the connection_timeout parameter
|
||||
to express timeouts with a microsecond resolution.
|
||||
|
||||
* FIX: TCP connections now respect the read/write timeout parameter when
|
||||
reading the payload of server responses. Previously, stream_get_contents()
|
||||
was being used internally to read data from a connection but it looks like
|
||||
PHP does not honour the specified timeout for socket streams when inside
|
||||
this function.
|
||||
|
||||
* FIX: The GET parameter for the SORT command now accepts also multiple key
|
||||
patterns by passing an array of strings. (ISSUE #1).
|
||||
|
||||
* FIX: Replies to the DEL command return the number of elements deleted by
|
||||
the server and not 0 or 1 interpreted as a boolean response. (ISSUE #4).
|
||||
|
||||
v0.5.1 (2010-01-23)
|
||||
* RPOPLPUSH has been changed from bulk command to inline command in Redis
|
||||
1.2.1, so ListPopLastPushHead now extends InlineCommand. The old RPOPLPUSH
|
||||
behavior is still available via the ListPopLastPushHeadBulk class so that
|
||||
you can override the server profile if you need the old (and uncorrect)
|
||||
behaviour when connecting to a Redis 1.2.0 instance.
|
||||
|
||||
* Added missing support for BGREWRITEAOF for Redis >= 1.2.0
|
||||
|
||||
* Implemented a factory method for the RedisServerProfile class to ease the
|
||||
creation of new server profile instances based on a version string.
|
||||
|
||||
v0.5.0 (2010-01-09)
|
||||
* First versioned release of Predis
|
||||
-368
@@ -1,368 +0,0 @@
|
||||
v0.7.1 (2011-12-27)
|
||||
===============================================================================
|
||||
|
||||
- The PEAR channel on PearHub has been deprecated in favour of `pear.nrk.io`.
|
||||
|
||||
- Miscellaneous minor fixes.
|
||||
|
||||
- Added transparent support for master / slave replication configurations where
|
||||
write operations are performed on the master server and read operations are
|
||||
routed to one of the slaves. Please refer to ISSUE #21 for a bit of history
|
||||
and more details about replication support in Predis.
|
||||
|
||||
- The `profile` client option now accepts a callable object used to initialize
|
||||
a new instance of `Predis\Profiles\IServerProfile`.
|
||||
|
||||
- Exposed a method for MULTI / EXEC contexts that adds the ability to execute
|
||||
instances of Redis commands against transaction objects.
|
||||
|
||||
|
||||
v0.7.0 (2011-12-11)
|
||||
===============================================================================
|
||||
|
||||
- Predis now adheres to the PSR-0 standard which means that there is no more a
|
||||
single file holding all the classes of the library, but multiple files (one
|
||||
for each class). You can use any PSR-0 compatible autoloader to load Predis
|
||||
or just leverage the default one shipped with the library by requiring the
|
||||
`Predis/Autoloader.php` and call `Predis\Autoloader::register()`.
|
||||
|
||||
- The default server profile for Redis is now 2.4. The `dev` profile supports
|
||||
all the features of Redis 2.6 (currently unstable) such as Lua scripting.
|
||||
|
||||
- Support for long aliases (method names) for Redis commands has been dropped.
|
||||
|
||||
- Redis 1.0 is no more supported. From now on Predis will use only the unified
|
||||
protocol to serialize commands.
|
||||
|
||||
- It is possible to prefix keys transparently on a client-level basis with the
|
||||
new `prefix` client option.
|
||||
|
||||
- An external connection factory is used to initialize new connection instances
|
||||
and developers can now register their own connection classes using the new
|
||||
`connections` client option.
|
||||
|
||||
- It is possible to connect locally to Redis using UNIX domain sockets. Just
|
||||
use `unix:///path/to/redis.sock` or a named array just like in the following
|
||||
example: `array('scheme' => 'unix', 'path' => '/path/to/redis.sock');`.
|
||||
|
||||
- If the `phpiredis` extension is loaded by PHP, it is now possible to use an
|
||||
alternative connection class that leverages it to make Predis faster on many
|
||||
cases, especially when dealing with big multibulk replies, with the the only
|
||||
downside that persistent connections are not supported. Please refer to the
|
||||
documentation to see how to activate this class using the new `connections`
|
||||
client option.
|
||||
|
||||
- Predis is capable to talk with Webdis, albeit with some limitations such as
|
||||
the lack of pipelining and transactions, just by using the `http` scheme in
|
||||
in the connection parameters. All is needed is PHP with the `curl` and the
|
||||
`phpiredis` extensions loaded.
|
||||
|
||||
- Way too many changes in the public API to make a list here, we just tried to
|
||||
make all the Redis commands compatible with previous releases of v0.6 so that
|
||||
you do not have to worry if you are simply using Predis as a client. Probably
|
||||
the only breaking changes that should be mentioned here are:
|
||||
|
||||
- `throw_on_error` has been renamed to `throw_errors` and it is a connection
|
||||
parameter instead of a client option, along with `iterable_multibulk`.
|
||||
|
||||
- `key_distribution` has been removed from the client options. To customize
|
||||
the distribution strategy you must provide a callable object to the new
|
||||
`cluster` client option to configure and then return a new instance of
|
||||
`Predis\Network\IConnectionCluster`.
|
||||
|
||||
- `Predis\Client::create()` has been removed. Just use the constructor to set
|
||||
up a new instance of `Predis\Client`.
|
||||
|
||||
- `Predis\Client::pipelineSafe()` was deprecated in Predis v0.6.1 and now has
|
||||
finally removed. Use `Predis\Client::pipeline(array('safe' => true))`.
|
||||
|
||||
- `Predis\Client::rawCommand()` has been removed due to inconsistencies with
|
||||
the underlying connection abstractions. You can still get the raw resource
|
||||
out of a connection with `Predis\Network\IConnectionSingle::getResource()`
|
||||
so that you can talk directly with Redis.
|
||||
|
||||
- The `Predis\MultiBulkCommand` class has been merged into `Predis\Command` and
|
||||
thus removed. Serialization of commands is now a competence of connections.
|
||||
|
||||
- The `Predis\IConnection` interface has been splitted into two new interfaces:
|
||||
`Predis\Network\IConnectionSingle` and `Predis\Network\IConnectionCluster`.
|
||||
|
||||
- The constructor of `Predis\Client` now accepts more type of arguments such as
|
||||
instances of `Predis\IConnectionParameters` and `Predis\Network\IConnection`.
|
||||
|
||||
|
||||
v0.6.6 (2011-04-01)
|
||||
===============================================================================
|
||||
|
||||
- Switched to Redis 2.2 as the default server profile (there are no changes
|
||||
that would break compatibility with previous releases). Long command names
|
||||
are no more supported by default but if you need them you can still require
|
||||
Predis_Compatibility.php to avoid breaking compatibility.
|
||||
|
||||
- Added a `VERSION` constant to `Predis\Client`.
|
||||
|
||||
- Some performance improvements for multibulk replies (parsing them is about
|
||||
16% faster than the previous version). A few core classes have been heavily
|
||||
optimized to reduce overhead when creating new instances.
|
||||
|
||||
- Predis now uses by default a new protocol reader, more lightweight and
|
||||
faster than the default handler-based one. Users can revert to the old
|
||||
protocol reader with the 'reader' client option set to `composable`.
|
||||
This client option can also accept custom reader classes implementing the
|
||||
new `Predis\IResponseReader` interface.
|
||||
|
||||
- Added support for connecting to Redis using UNIX domain sockets (ISSUE #25).
|
||||
|
||||
- The `read_write_timeout` connection parameter can now be set to 0 or false
|
||||
to disable read and write timeouts on connections. The old behaviour of -1
|
||||
is still intact.
|
||||
|
||||
- `ZUNIONSTORE` and `ZINTERSTORE` can accept an array to specify a list of the
|
||||
source keys to be used to populate the destination key.
|
||||
|
||||
- `MGET`, `SINTER`, `SUNION` and `SDIFF` can accept an array to specify a list
|
||||
of keys. `SINTERSTORE`, `SUNIONSTORE` and `SDIFFSTORE` can also accept an
|
||||
array to specify the list of source keys.
|
||||
|
||||
- `SUBSCRIBE` and `PSUBSCRIBE` can accept a list of channels for subscription.
|
||||
|
||||
- __FIX__: some client-side clean-ups for `MULTI/EXEC` were handled incorrectly
|
||||
in a couple of corner cases (ISSUE #27).
|
||||
|
||||
|
||||
v0.6.5 (2011-02-12)
|
||||
===============================================================================
|
||||
|
||||
- __FIX__: due to an untested internal change introduced in v0.6.4, a wrong
|
||||
handling of bulk reads of zero-length values was producing protocol
|
||||
desynchronization errors (ISSUE #20).
|
||||
|
||||
|
||||
v0.6.4 (2011-02-12)
|
||||
===============================================================================
|
||||
|
||||
- Various performance improvements (15% ~ 25%) especially when dealing with
|
||||
long multibulk replies or when using clustered connections.
|
||||
|
||||
- Added the `on_retry` option to `Predis\MultiExecBlock` that can be used to
|
||||
specify an external callback (or any callable object) that gets invoked
|
||||
whenever a transaction is aborted by the server.
|
||||
|
||||
- Added inline (p)subscribtion via options when initializing an instance of
|
||||
`Predis\PubSubContext`.
|
||||
|
||||
|
||||
v0.6.3 (2011-01-01)
|
||||
===============================================================================
|
||||
|
||||
- New commands available in the Redis v2.2 profile (dev):
|
||||
- Strings: `SETRANGE`, `GETRANGE`, `SETBIT`, `GETBIT`
|
||||
- Lists : `BRPOPLPUSH`
|
||||
|
||||
- The abstraction for `MULTI/EXEC` transactions has been dramatically improved
|
||||
by providing support for check-and-set (CAS) operations when using Redis >=
|
||||
2.2. Aborted transactions can also be optionally replayed in automatic up
|
||||
to a user-defined number of times, after which a `Predis\AbortedMultiExec`
|
||||
exception is thrown.
|
||||
|
||||
|
||||
v0.6.2 (2010-11-28)
|
||||
===============================================================================
|
||||
|
||||
- Minor internal improvements and clean ups.
|
||||
|
||||
- New commands available in the Redis v2.2 profile (dev):
|
||||
- Strings: `STRLEN`
|
||||
- Lists : `LINSERT`, `RPUSHX`, `LPUSHX`
|
||||
- ZSets : `ZREVRANGEBYSCORE`
|
||||
- Misc. : `PERSIST`
|
||||
|
||||
- WATCH also accepts a single array parameter with the keys that should be
|
||||
monitored during a transaction.
|
||||
|
||||
- Improved the behaviour of `Predis\MultiExecBlock` in certain corner cases.
|
||||
|
||||
- Improved parameters checking for the SORT command.
|
||||
|
||||
- __FIX__: the `STORE` parameter for the `SORT` command didn't work correctly
|
||||
when using `0` as the target key (ISSUE #13).
|
||||
|
||||
- __FIX__: the methods for `UNWATCH` and `DISCARD` do not break anymore method
|
||||
chaining with `Predis\MultiExecBlock`.
|
||||
|
||||
|
||||
v0.6.1 (2010-07-11)
|
||||
===============================================================================
|
||||
|
||||
- Minor internal improvements and clean ups.
|
||||
|
||||
- New commands available in the Redis v2.2 profile (dev):
|
||||
- Misc. : `WATCH`, `UNWATCH`
|
||||
|
||||
- Optional modifiers for `ZRANGE`, `ZREVRANGE` and `ZRANGEBYSCORE` queries are
|
||||
supported using an associative array passed as the last argument of their
|
||||
respective methods.
|
||||
|
||||
- The `LIMIT` modifier for `ZRANGEBYSCORE` can be specified using either:
|
||||
- an indexed array: `array($offset, $count)`
|
||||
- an associative array: `array('offset' => $offset, 'count' => $count)`
|
||||
|
||||
- The method `Predis\Client::__construct()` now accepts also instances of
|
||||
`Predis\ConnectionParameters`.
|
||||
|
||||
- `Predis\MultiExecBlock` and `Predis\PubSubContext` now throw an exception
|
||||
when trying to create their instances using a profile that does not
|
||||
support the required Redis commands or when the client is connected to
|
||||
a cluster of connections.
|
||||
|
||||
- Various improvements to `Predis\MultiExecBlock`:
|
||||
- fixes and more consistent behaviour across various usage cases.
|
||||
- support for `WATCH` and `UNWATCH` when using the current development
|
||||
profile (Redis v2.2) and aborted transactions.
|
||||
|
||||
- New signature for `Predis\Client::multiExec()` which is now able to accept
|
||||
an array of options for the underlying instance of `Predis\MultiExecBlock`.
|
||||
Backwards compatibility with previous releases of Predis is ensured.
|
||||
|
||||
- New signature for `Predis\Client::pipeline()` which is now able to accept
|
||||
an array of options for the underlying instance of Predis\CommandPipeline.
|
||||
Backwards compatibility with previous releases of Predis is ensured.
|
||||
The method `Predis\Client::pipelineSafe()` is to be considered deprecated.
|
||||
|
||||
- __FIX__: The `WEIGHT` modifier for `ZUNIONSTORE` and `ZINTERSTORE` was
|
||||
handled incorrectly with more than two weights specified.
|
||||
|
||||
|
||||
v0.6.0 (2010-05-24)
|
||||
===============================================================================
|
||||
|
||||
- Switched to the new multi-bulk request protocol for all of the commands
|
||||
in the Redis 1.2 and Redis 2.0 profiles. Inline and bulk requests are now
|
||||
deprecated as they will be removed in future releases of Redis.
|
||||
|
||||
- The default server profile is `2.0` (targeting Redis 2.0.x). If you are
|
||||
using older versions of Redis, it is highly recommended that you specify
|
||||
which server profile the client should use (e.g. `1.2` when connecting
|
||||
to instances of Redis 1.2.x).
|
||||
|
||||
- Support for Redis 1.0 is now optional and it is provided by requiring
|
||||
'Predis_Compatibility.php' before creating an instance of Predis\Client.
|
||||
|
||||
- New commands added to the Redis 2.0 profile since Predis 0.5.1:
|
||||
- Strings: `SETEX`, `APPEND`, `SUBSTR`
|
||||
- ZSets : `ZCOUNT`, `ZRANK`, `ZUNIONSTORE`, `ZINTERSTORE`, `ZREMBYRANK`,
|
||||
`ZREVRANK`
|
||||
- Hashes : `HSET`, `HSETNX`, `HMSET`, `HINCRBY`, `HGET`, `HMGET`, `HDEL`,
|
||||
`HEXISTS`, `HLEN`, `HKEYS`, `HVALS`, `HGETALL`
|
||||
- PubSub : `PUBLISH`, `SUBSCRIBE`, `UNSUBSCRIBE`
|
||||
- Misc. : `DISCARD`, `CONFIG`
|
||||
|
||||
- Introduced client-level options with the new `Predis\ClientOptions` class.
|
||||
Options can be passed to the constructor of `Predis\Client` in its second
|
||||
argument as an array or an instance of Predis\ClientOptions. For brevity's
|
||||
sake and compatibility with older versions, the constructor still accepts
|
||||
an instance of `Predis\RedisServerProfile` in its second argument. The
|
||||
currently supported client options are:
|
||||
|
||||
- `profile` [default: `2.0` as of Predis 0.6.0]: specifies which server
|
||||
profile to use when connecting to Redis. This option accepts an instance
|
||||
of `Predis\RedisServerProfile` or a string that indicates the version.
|
||||
|
||||
- `key_distribution` [default: `Predis\Distribution\HashRing`]: specifies
|
||||
which key distribution strategy to use to distribute keys among the
|
||||
servers that compose a cluster. This option accepts an instance of
|
||||
`Predis\Distribution\IDistributionStrategy` so that users can implement
|
||||
their own key distribution strategy. `Predis\Distribution\KetamaPureRing`
|
||||
is an alternative distribution strategy providing a pure-PHP implementation
|
||||
of the same algorithm used by libketama.
|
||||
|
||||
- `throw_on_error` [default: `TRUE`]: server errors can optionally be handled
|
||||
"silently": instead of throwing an exception, the client returns an error
|
||||
response type.
|
||||
|
||||
- `iterable_multibulk` [EXPERIMENTAL - default: `FALSE`]: in addition to the
|
||||
classic way of fetching a whole multibulk reply into an array, the client
|
||||
can now optionally stream a multibulk reply down to the user code by using
|
||||
PHP iterators. It is just a little bit slower, but it can save a lot of
|
||||
memory in certain scenarios.
|
||||
|
||||
- New parameters for connections:
|
||||
|
||||
- `alias` [default: not set]: every connection can now be identified by an
|
||||
alias that is useful to get a specific connections when connected to a
|
||||
cluster of Redis servers.
|
||||
- `weight` [default: not set]: allows to balance keys asymmetrically across
|
||||
multiple servers. This is useful when you have servers with different
|
||||
amounts of memory to distribute the load of your keys accordingly.
|
||||
- `connection_async` [default: `FALSE`]: estabilish connections to servers
|
||||
in a non-blocking way, so that the client is not blocked while the socket
|
||||
resource performs the actual connection.
|
||||
- `connection_persistent` [default: `FALSE`]: the underlying socket resource
|
||||
is left open when a script ends its lifecycle. Persistent connections can
|
||||
lead to unpredictable or strange behaviours, so they should be used with
|
||||
extreme care.
|
||||
|
||||
- Introduced the `Predis\Pipeline\IPipelineExecutor` interface. Classes that
|
||||
implements this interface are used internally by the `Predis\CommandPipeline`
|
||||
class to change the behaviour of the pipeline when writing/reading commands
|
||||
from one or multiple servers. Here is the list of the default executors:
|
||||
|
||||
- `Predis\Pipeline\StandardExecutor`: exceptions generated by server errors
|
||||
might be thrown depending on the options passed to the client (see the
|
||||
`throw_on_error` client option). Instead, protocol or network errors always
|
||||
throw exceptions. This is the default executor for single and clustered
|
||||
connections and shares the same behaviour of Predis 0.5.x.
|
||||
- `Predis\Pipeline\SafeExecutor`: exceptions generated by server, protocol
|
||||
or network errors are not thrown but returned in the response array as
|
||||
instances of `Predis\ResponseError` or `Predis\CommunicationException`.
|
||||
- `Predis\Pipeline\SafeClusterExecutor`: this executor shares the same
|
||||
behaviour of `Predis\Pipeline\SafeExecutor` but it is geared towards
|
||||
clustered connections.
|
||||
|
||||
- Support for PUB/SUB is handled by the new `Predis\PubSubContext` class, which
|
||||
could also be used to build a callback dispatcher for PUB/SUB scenarios.
|
||||
|
||||
- When connected to a cluster of connections, it is now possible to get a
|
||||
new `Predis\Client` instance for a single connection of the cluster by
|
||||
passing its alias/index to the new `Predis\Client::getClientFor()` method.
|
||||
|
||||
- `Predis\CommandPipeline` and `Predis\MultiExecBlock` return their instances
|
||||
when invokink commands, thus allowing method chaining in pipelines and
|
||||
multi-exec blocks.
|
||||
|
||||
- `Predis\MultiExecBlock` can handle the new `DISCARD` command.
|
||||
|
||||
- Connections now support float values for the `connection_timeout` parameter
|
||||
to express timeouts with a microsecond resolution.
|
||||
|
||||
- __FIX__: TCP connections now respect the read/write timeout parameter when
|
||||
reading the payload of server responses. Previously, `stream_get_contents()`
|
||||
was being used internally to read data from a connection but it looks like
|
||||
PHP does not honour the specified timeout for socket streams when inside
|
||||
this function.
|
||||
|
||||
- __FIX__: The `GET` parameter for the `SORT` command now accepts also multiple
|
||||
key patterns by passing an array of strings. (ISSUE #1).
|
||||
|
||||
* __FIX__: Replies to the `DEL` command return the number of elements deleted
|
||||
by the server and not 0 or 1 interpreted as a boolean response. (ISSUE #4).
|
||||
|
||||
|
||||
v0.5.1 (2010-01-23)
|
||||
===============================================================================
|
||||
|
||||
* `RPOPLPUSH` has been changed from bulk command to inline command in Redis
|
||||
1.2.1, so `ListPopLastPushHead` now extends `InlineCommand`. The old behavior
|
||||
is still available via the `ListPopLastPushHeadBulk` class so that you can
|
||||
override the server profile if you need the old (and uncorrect) behaviour
|
||||
when connecting to a Redis 1.2.0 instance.
|
||||
|
||||
* Added missing support for `BGREWRITEAOF` for Redis >= 1.2.0.
|
||||
|
||||
* Implemented a factory method for the `RedisServerProfile` class to ease the
|
||||
creation of new server profile instances based on a version string.
|
||||
|
||||
|
||||
v0.5.0 (2010-01-09)
|
||||
===============================================================================
|
||||
* First versioned release of Predis
|
||||
@@ -1,79 +0,0 @@
|
||||
# Some frequently asked questions about the performances of Predis #
|
||||
____________________________________________
|
||||
|
||||
|
||||
### Predis is a pure-PHP implementation: it can not be fast enough! ###
|
||||
|
||||
It really depends, but most of the times the answer is: _yes, it is fast enough_. I will give you
|
||||
a couple of easy numbers using a single Predis client with PHP 5.3.5 (custom build) and Redis 2.2
|
||||
(localhost) under Ubuntu 11.04 (running on a Intel Q6600):
|
||||
|
||||
19600 SET/sec using 12 bytes for both key and value
|
||||
18900 GET/sec while retrieving the very same values
|
||||
0.200 seconds to fetch 30000 keys using _KEYS *_.
|
||||
|
||||
How does it compare with a nice C-based extension such as [__phpredis__](http://github.com/nicolasff/phpredis)?
|
||||
|
||||
30500 SET/sec using 12 bytes for both key and value
|
||||
31000 GET/sec while retrieving the very same values
|
||||
0.030 seconds to fetch 30000 keys using "KEYS *"".
|
||||
|
||||
Wow, __phpredis__ looks so much faster! Well we are comparing a C extension with a pure-PHP library so
|
||||
lower numbers are quite expected, but there is a fundamental flaw in them: is this really how you are
|
||||
going to use Redis in your application? Are you really going to send thousands of commands in a for-loop
|
||||
for each page request using a single client instance? If so, well I guess you are probably doing something
|
||||
wrong. Also, if you need to SET or GET multiple keys you should definitely use commands such as MSET and
|
||||
MGET. You can also use pipelining to get more performances when this technique can be used.
|
||||
|
||||
There is one more thing. We have tested the overhead of Predis by connecting on a localhost instance of
|
||||
Redis, but how these numbers change when we hit the network by connecting to instances of Redis that
|
||||
reside on other servers?
|
||||
|
||||
Using Predis:
|
||||
3600 SET/sec using 12 bytes for both key and value
|
||||
3600 GET/sec while retrieving the very same values
|
||||
0.210 seconds to fetch 30000 keys using "KEYS *".
|
||||
|
||||
Using phpredis:
|
||||
4000 SET/sec using 12 bytes for both key and value
|
||||
4000 GET/sec while retrieving the very same values
|
||||
0.051 seconds to fetch 30000 keys using "KEYS *".
|
||||
|
||||
There you go, you get almost the same average numbers and the reason is quite simple: network latency
|
||||
is a real performance killer and you cannot do (almost) anything about that. As a disclaimer, please
|
||||
remember that we are measuring the overhead of client libraries implementations and the effects of the
|
||||
network round-trip time, we are not really measuring how fast Redis is. Redis shines the best with
|
||||
thousands of concurrent clients doing requests! Also, actual performances should be measured according
|
||||
to how your application will use Redis.
|
||||
|
||||
|
||||
### I am convinced, but performances for multi-bulk replies (e.g. _KEYS *_) are still worse ###
|
||||
|
||||
Fair enough, but there is actually an option for you if you need even more speed and it consists on
|
||||
installing __[phpiredis](http://github.com/seppo0010/phpiredis)__ (note the additional _i_ in the
|
||||
name) and let Predis using it. __phpiredis__ is a C-based extension that wraps __hiredis__ (the
|
||||
official Redis C client library) with a thin layer that exposes its features to PHP. You will now
|
||||
get the benefits of a faster protocol parser just by adding a single line of code in your application:
|
||||
|
||||
$client = new Predis\Client('tcp://127.0.0.1', array(
|
||||
'connections' => array('tcp' => 'Predis\Network\PhpiredisConnection')
|
||||
));
|
||||
|
||||
As simple as it is, nothing will really change in the way you use the library in your application. So,
|
||||
how fast is it now? There are not much improvements for inline or short bulk replies (e.g. _SET_ or
|
||||
_GET_), but the speed for parsing multi-bulk replies is now on par with phpredis:
|
||||
|
||||
Using Predis with a phpiredis-based connection to fetch 30000 keys using _KEYS *_:
|
||||
|
||||
0.031 seconds from a local Redis instance
|
||||
0.058 seconds from a remote Redis instance
|
||||
|
||||
|
||||
### If I need to install a C extension to get better performances, why not using phpredis? ###
|
||||
|
||||
Good question. Generically speaking, if you need absolute uber-speed using localhost instances of Redis
|
||||
and you do not care about abstractions built around some Redis features such as MULTI / EXEC, or if you
|
||||
do not need any kind of extensibility or guaranteed backwards compatibility with different versions of
|
||||
Redis (Predis currently supports from 1.2 up to 2.2, and even the current development version), then
|
||||
using __phpredis__ can make sense for you. Otherwise, Predis is for you. Using __phpiredis__ gives you
|
||||
a nice speed bump, but it is not mandatory.
|
||||
@@ -1,58 +0,0 @@
|
||||
# Some frequently asked questions about Predis #
|
||||
____________________________________________
|
||||
|
||||
|
||||
### What is the point of Predis? ###
|
||||
|
||||
The main point of Predis is about offering a highly customizable client for Redis that can be easily
|
||||
extended by developers while still being reasonabily fast. With Predis you can swap almost any class
|
||||
used internally with your own custom implementation: you can build connection classes, or new
|
||||
distribution strategies for client-side sharding, or class handlers to replace existing commands or
|
||||
add new ones. All of this can be achieved without messing with the source code of the library and
|
||||
directly in your own application. Given the fast pace at which Redis is developed and adds new
|
||||
features, this can be a great asset that allows you to add new and still missing features or commands,
|
||||
or change the behaviour of the library without the need to break your dependencies in production code
|
||||
(well, at least to some degree).
|
||||
|
||||
|
||||
### How about performances? ###
|
||||
|
||||
Please refer to the dedicated __FAQ.PERFORMANCES__ file.
|
||||
|
||||
|
||||
### Why PHP 5.3? ###
|
||||
|
||||
Seriously, are you still using PHP 5.2 to build new applications? I assume that if you are throwing Redis
|
||||
in the mix, then you are probably coding something new after all. PHP 5.3 is faster, less memory hungry
|
||||
and has a few nice features such as namespaces and closures (kind of). More importantly, PHP 5.2 is not
|
||||
even officially supported anymore (aside from security patches). PHP 5.3 is not the future of PHP, but
|
||||
its current present. Furthermore, most of the existing frameworks out there are also making the switch
|
||||
with their respective new major versions. If you still insist on using PHP 5.2, you can get any recent
|
||||
backported release of Predis 0.6.x, or just use a different library.
|
||||
|
||||
|
||||
### Why so many files for just one library? ###
|
||||
|
||||
Before v0.7, Predis used the one-big-file approach to distribute the library. As much as you prefer having
|
||||
just one file for everything, this kind of solution is actually not that good. Predis now complies with the
|
||||
[PSR-0](http://groups.google.com/group/php-standards/web/psr-0-final-proposal) standard to play nice with
|
||||
the major recent frameworks and libraries, so it needs an autoloader function to be defined. If you still
|
||||
want to have just one file grouping all the classes for whatever reason, then the __bin/create-single-file.php__
|
||||
script in the repository can generate it for you. There is also the __bin/create-phar.php__ script that
|
||||
generates a single [Phar archive](http://www.php.net/manual/en/intro.phar.php) of the whole library.
|
||||
|
||||
|
||||
### Does Predis support UNIX domain sockets and persistent connections? ###
|
||||
|
||||
Yes. Obviously, persistent connections actually work when using PHP configured as a persistent process that
|
||||
gets recycled between requests (see [PHP-FPM](http://php-fpm.org/)).
|
||||
|
||||
|
||||
### Does Predis support transparent (de)serialization of values? ###
|
||||
|
||||
No, and it will not ever do that for you by default. The reason behind this decision is that serialization
|
||||
is usually something that developers prefer to customize depending on their needs and can not be easily
|
||||
generalized when using Redis because of the many possible access patterns for the data. This does not
|
||||
mean that it is impossible to have such a feature, you can leverage Predis' extensibility to define your
|
||||
own serialization-aware commands. See [here](http://github.com/nrk/predis/issues/29#issuecomment-1202624)
|
||||
for more details on how to implement such a feature with a practical example.
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2011 Daniele Alessandri
|
||||
Copyright (c) 2009-2010 Daniele Alessandri
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
# Predis #
|
||||
|
||||
## About ##
|
||||
|
||||
Predis is a flexible and feature-complete PHP client library for the Redis key-value
|
||||
database. It currently comes in two flavors:
|
||||
|
||||
- the mainline client library, which targets PHP 5.3.x and leverages a lot of the
|
||||
features introduced in this new version of the PHP interpreter.
|
||||
- a backport to PHP 5.2.x for those who can not upgrade their environment yet
|
||||
(it admittedly has a lower priority compared to the mainline library, although we
|
||||
try to keep the two versions aligned as much as possible).
|
||||
|
||||
Please refer to the TODO file to see which issues are still pending and what is due
|
||||
to be implemented soon in Predis.
|
||||
|
||||
|
||||
## Main features ##
|
||||
|
||||
- Full support for Redis 2.0. Different versions of Redis are supported via server profiles.
|
||||
- Client-side sharding (support for consistent hashing and custom distribution strategies).
|
||||
- Command pipelining on single and multiple connections (transparent).
|
||||
- Abstraction for Redis transactions (>= 2.0) with support for CAS operations (>= 2.2).
|
||||
- Lazy connections (connections to Redis instances are only established just in time).
|
||||
- Flexible system to define and register your own set of commands to a client instance.
|
||||
|
||||
|
||||
## Quick examples ##
|
||||
|
||||
See the [official wiki](http://wiki.github.com/nrk/predis) of the project for a more
|
||||
complete coverage of all the features available in Predis.
|
||||
|
||||
### Connecting to a local instance of Redis ###
|
||||
|
||||
You don't have to specify a tcp host and port when connecting to Redis instances
|
||||
running on the localhost on the default port:
|
||||
|
||||
$redis = new Predis_Client();
|
||||
$redis->set('library', 'predis');
|
||||
$value = $redis->get('library');
|
||||
|
||||
|
||||
### Pipelining multiple commands to a remote instance of Redis ##
|
||||
|
||||
Pipelining helps with performances when there is the need to issue many commands
|
||||
to a server in one go:
|
||||
|
||||
$redis = new Predis_Client('redis://10.0.0.1:6379/');
|
||||
$pipe = $redis->pipeline();
|
||||
$pipe->ping();
|
||||
$pipe->incrby('counter', 10);
|
||||
$pipe->incrby('counter', 30);
|
||||
$pipe->get('counter');
|
||||
$replies = $pipe->execute();
|
||||
|
||||
|
||||
### Pipelining multiple commands to multiple instances of Redis (sharding) ##
|
||||
|
||||
Predis supports data sharding using consistent-hashing on keys on the client side.
|
||||
Furthermore, a pipeline can be initialized on a cluster of redis instances in the
|
||||
same exact way they are created on single connection. Sharding is still transparent
|
||||
to the user:
|
||||
|
||||
$redis = new Predis_Client(array(
|
||||
array('host' => '10.0.0.1', 'port' => 6379),
|
||||
array('host' => '10.0.0.2', 'port' => 6379)
|
||||
));
|
||||
|
||||
$pipe = $redis->pipeline();
|
||||
for ($i = 0; $i < 1000; $i++) {
|
||||
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
|
||||
$pipe->get("key:$i");
|
||||
}
|
||||
$replies = $pipe->flushPipeline();
|
||||
|
||||
|
||||
### Definition and runtime registration of new commands on the client ###
|
||||
|
||||
Let's suppose Redis just added the support for a brand new feature associated
|
||||
with a new command. If you want to start using the above mentioned new feature
|
||||
right away without messing with Predis source code or waiting for it to find
|
||||
its way into a stable Predis release, then you can start off by creating a new
|
||||
class that matches the command type and its behaviour and then bind it to a
|
||||
client instance at runtime. Actually, it is easier done than said:
|
||||
|
||||
class BrandNewRedisCommand extends Predis_MultiBulkCommand {
|
||||
public function getCommandId() { return 'NEWCMD'; }
|
||||
}
|
||||
|
||||
$redis = new Predis_Client();
|
||||
$redis->getProfile()->registerCommand('BrandNewRedisCommand', 'newcmd');
|
||||
$redis->newcmd();
|
||||
|
||||
|
||||
## Development ##
|
||||
|
||||
Predis is fully backed up by a test suite which tries to cover all the aspects of the
|
||||
client library and the interaction of every single command with a Redis server. If you
|
||||
want to work on Predis, it is highly recommended that you first run the test suite to
|
||||
be sure that everything is OK, and report strange behaviours or bugs.
|
||||
|
||||
The recommended way to contribute to Predis is to fork the project on GitHub, fix or
|
||||
add features on your newly created repository and then submit issues on the Predis
|
||||
issue tracker with a link to your repository. Obviously, you can use any other Git
|
||||
hosting provider of you preference. Diff patches will be accepted too, even though
|
||||
they are not the preferred way to contribute to Predis.
|
||||
|
||||
When modifying Predis please be sure that no warnings or notices are emitted by PHP
|
||||
by running the interpreter in your development environment with the "error_reporting"
|
||||
variable set to E_ALL | E_STRICT.
|
||||
|
||||
|
||||
## Dependencies ##
|
||||
|
||||
- PHP >= 5.3.0 (for the mainline client library)
|
||||
- PHP >= 5.2.6 (for the backported client library)
|
||||
- PHPUnit (needed to run the test suite)
|
||||
|
||||
## Links ##
|
||||
|
||||
### Project ###
|
||||
- [Source code](http://github.com/nrk/predis/)
|
||||
- [Wiki](http://wiki.github.com/nrk/predis/)
|
||||
- [Issue tracker](http://github.com/nrk/predis/issues)
|
||||
|
||||
### Related ###
|
||||
- [Redis](http://code.google.com/p/redis/)
|
||||
- [PHP](http://php.net/)
|
||||
- [PHPUnit](http://www.phpunit.de/)
|
||||
- [Git](http://git-scm.com/)
|
||||
|
||||
## Author ##
|
||||
|
||||
[Daniele Alessandri](mailto:suppakilla@gmail.com)
|
||||
|
||||
## Contributors ##
|
||||
|
||||
[Lorenzo Castelli](http://github.com/lcastelli)
|
||||
|
||||
## License ##
|
||||
|
||||
The code for Predis is distributed under the terms of the MIT license (see LICENSE).
|
||||
@@ -1,223 +0,0 @@
|
||||
# Predis #
|
||||
|
||||
Predis is a flexible and feature-complete PHP (>= 5.3) client library for the Redis key-value store.
|
||||
|
||||
For a list of frequently asked questions about Predis, see the __FAQ__ file in the root of the repository.
|
||||
For a version compatible with PHP 5.2 you must use the backported version from the latest release in the
|
||||
0.6.x series. More details are available on the [official wiki](http://wiki.github.com/nrk/predis) of the
|
||||
project,
|
||||
|
||||
|
||||
## Main features ##
|
||||
|
||||
- Complete support for Redis from __1.2__ to __2.4__ and the current development versions using different
|
||||
server profiles.
|
||||
- Client-side sharding with support for consistent hashing or custom distribution strategies.
|
||||
- Support for master / slave replication configurations (write on master, read from slaves).
|
||||
- Command pipelining on single and aggregated connections.
|
||||
- Transparent key prefixing strategy capable of handling any command known that has keys in its arguments.
|
||||
- Abstraction for Redis transactions (Redis >= 2.0) with support for CAS operations (Redis >= 2.2).
|
||||
- Connections to Redis instances are automatically and lazily estabilished upon the first call to a command.
|
||||
- Ability to connect to Redis using TCP/IP or UNIX domain sockets with support for persistent connections.
|
||||
- Ability to use alternative connection classes to use different types of network or protocol backends.
|
||||
- Flexible system to define and register your own set of commands or server profiles to client instances.
|
||||
|
||||
|
||||
## How to use Predis ##
|
||||
|
||||
Predis is available on [Packagist](http://packagist.org/packages/predis/predis) for an easy installation
|
||||
using [Composer](http://packagist.org/about-composer). Composer helps you manage dependencies for your
|
||||
projects and libraries without much hassle which makes it the preferred way to get up and running with
|
||||
new applications. Alternatively, the library is available on our [own PEAR channel](http://pear.nrk.io)
|
||||
for a more traditional installation via PEAR. Zip and tar.gz archives are also downloadable from GitHub
|
||||
by browsing the list of [tagged releases](http://github.com/nrk/predis/tags).
|
||||
|
||||
|
||||
### Loading the library ###
|
||||
|
||||
To automatically load all of its files, Predis relies on the autoloading features of PHP and complies
|
||||
with the [PSR-0 standard](http://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) for
|
||||
interoperability with most of the major frameworks and libraries. Everything is transparently handled
|
||||
for you when installing the library using Composer, but you can also leverage its own autoloader class
|
||||
if you are going to use it in a project or script without any PSR-0 compliant autoloading facility:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
// prepend a base path if Predis is not present in your "include_path".
|
||||
require 'Predis/Autoloader.php';
|
||||
|
||||
Predis\Autoloader::register();
|
||||
```
|
||||
|
||||
You can create a single [Phar](http://www.php.net/manual/en/intro.phar.php) archive from the repository
|
||||
just by launching the `bin/create-phar.php` executable script. The generated Phar archive ships with a
|
||||
stub defining an autoloader function for Predis, so you just need to require the Phar to be able to use
|
||||
the library.
|
||||
|
||||
Alternatively you can generate a single PHP file that holds every class, just like older versions of
|
||||
Predis, using the `bin/create-single-file.php` executable script. In this way you can load Predis in your
|
||||
scripts simply by using functions such as `require` and `include`, but this practice is not encouraged.
|
||||
|
||||
|
||||
### Connecting to a local instance of Redis ###
|
||||
|
||||
When connecting to local instance of Redis (`127.0.0.1` on port `6379`), you do not have to specify any
|
||||
additional parameter to create a new client instance:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$redis = new Predis\Client();
|
||||
$redis->set('foo', 'bar');
|
||||
$value = $redis->get('foo');
|
||||
```
|
||||
|
||||
However you can use an URI string or a named array to specify the needed connection parameters:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$redis = new Predis\Client('tcp://10.0.0.1:6379');
|
||||
|
||||
// is equivalent to:
|
||||
|
||||
$redis = new Predis\Client(array(
|
||||
'scheme' => 'tcp',
|
||||
'host' => '10.0.0.1',
|
||||
'port' => 6379,
|
||||
));
|
||||
```
|
||||
|
||||
|
||||
### Pipelining multiple commands to multiple instances of Redis with client-side sharding ###
|
||||
|
||||
Pipelining helps with performances when there is the need to send many commands to a server in one go.
|
||||
Furthermore, pipelining works transparently even on aggregated connections. To achieve this, Predis
|
||||
supports client-side sharding using consistent-hashing on keys while clustered connections are supported
|
||||
natively by the client class.
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$redis = new Predis\Client(array(
|
||||
array('host' => '10.0.0.1', 'port' => 6379),
|
||||
array('host' => '10.0.0.2', 'port' => 6379)
|
||||
));
|
||||
|
||||
$replies = $redis->pipeline(function($pipe) {
|
||||
for ($i = 0; $i < 1000; $i++) {
|
||||
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
|
||||
$pipe->get("key:$i");
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Overriding standard connection classes with custom ones ###
|
||||
|
||||
Predis allows developers to create new connection classes to add support for new protocols or override
|
||||
the existing ones and provide a different implementation compared to the default classes. This can be
|
||||
obtained by subclassing the `Predis\Network\IConnectionSingle` interface.
|
||||
|
||||
``` php
|
||||
<?php
|
||||
class MyConnectionClass implements Predis\Network\IConnectionSingle
|
||||
{
|
||||
// implementation goes here
|
||||
}
|
||||
|
||||
// Let Predis automatically use your own class to handle connections identified by the tcp scheme.
|
||||
$client = new Predis\Client('tcp://127.0.0.1', array(
|
||||
'connections' => array('tcp' => 'MyConnectionClass')
|
||||
));
|
||||
```
|
||||
|
||||
The classes contained in the `Predis\Network` namespace give you a better insight with actual code on
|
||||
how to create new connection classes.
|
||||
|
||||
|
||||
### Defining and registering new commands on the client at runtime ###
|
||||
|
||||
Let's suppose Redis just added the support for a brand new feature associated with a new command. If
|
||||
you want to start using the above mentioned new feature right away without messing with Predis source
|
||||
code or waiting for it to find its way into a stable Predis release, then you can start off by creating
|
||||
a new class that matches the command type and its behaviour and then bind it to a client instance at
|
||||
runtime. Actually, it is easier done than said:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
class BrandNewRedisCommand extends Predis\Commands\Command
|
||||
{
|
||||
public function getId()
|
||||
{
|
||||
return 'NEWCMD';
|
||||
}
|
||||
}
|
||||
|
||||
$redis = new Predis\Client();
|
||||
$redis->getProfile()->defineCommand('newcmd', 'BrandNewRedisCommand');
|
||||
$redis->newcmd();
|
||||
```
|
||||
|
||||
|
||||
## Test suite ##
|
||||
|
||||
__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. The suite performs integration
|
||||
tests against a running instance of Redis (>= 2.4.0 is required) to verify the correct behaviour of the
|
||||
implementation of each command and automatically skips commands not defined in the selected version of
|
||||
Redis. 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 server profile for Redis v2.4 (which is the
|
||||
current stable version of Redis). You can optionally run the suite against a Redis instance built from
|
||||
the `unstable` branch with the development profile by changing the `REDIS_SERVER_VERSION` to `dev` in
|
||||
the `phpunit.xml` file. More details about testing Predis are available in `tests/README.md`.
|
||||
|
||||
Predis uses Travis CI for continuous integration. You can find the results of the test suite and the build
|
||||
history [on its project page](http://travis-ci.org/nrk/predis).
|
||||
|
||||
|
||||
## Contributing ##
|
||||
|
||||
If you want to work on Predis, it is highly recommended that you first run the test suite in order to
|
||||
check that everything is OK, and report strange behaviours or bugs. When modifying Predis please make
|
||||
sure that no warnings or notices are emitted by PHP by running the interpreter in your development
|
||||
environment with the `error_reporting` variable set to `E_ALL | E_STRICT`.
|
||||
|
||||
The recommended way to contribute to Predis is to fork the project on GitHub, create new topic branches
|
||||
on your newly created repository to fix or add features (possibly with tests covering your modifications)
|
||||
and then open a new pull request with a description of the applied changes. Obviously you can use any
|
||||
other Git hosting provider of your preference.
|
||||
|
||||
|
||||
## Dependencies ##
|
||||
|
||||
- PHP >= 5.3.2
|
||||
- PHPUnit >= 3.5.0 (needed to run the test suite)
|
||||
|
||||
## Links ##
|
||||
|
||||
### Project ###
|
||||
- [Source code](http://github.com/nrk/predis/)
|
||||
- [Wiki](http://wiki.github.com/nrk/predis/)
|
||||
- [Issue tracker](http://github.com/nrk/predis/issues)
|
||||
- [PEAR channel](http://pear.nrk.io)
|
||||
|
||||
### Related ###
|
||||
- [Redis](http://redis.io/)
|
||||
- [PHP](http://php.net/)
|
||||
- [PHPUnit](http://www.phpunit.de/)
|
||||
- [Git](http://git-scm.com/)
|
||||
|
||||
## Author ##
|
||||
|
||||
- [Daniele Alessandri](mailto:suppakilla@gmail.com) ([twitter](http://twitter.com/JoL1hAHN))
|
||||
|
||||
## Contributors ##
|
||||
|
||||
- [Lorenzo Castelli](http://github.com/lcastelli)
|
||||
- [Jordi Boggiano](http://github.com/Seldaek) ([twitter](http://twitter.com/seldaek))
|
||||
- [Sebastian Waisbrot](http://github.com/seppo0010) ([twitter](http://twitter.com/seppo0010))
|
||||
for his work on extending [phpiredis](http://github.com/seppo0010/phpiredis) for Predis
|
||||
|
||||
## License ##
|
||||
|
||||
The code for Predis is distributed under the terms of the MIT license (see LICENSE).
|
||||
@@ -1,4 +1,7 @@
|
||||
* Documentation! The README is obviously not enought to show how to use Predis
|
||||
as it does not cover all of its features.
|
||||
* Documentation! The README is obviously not enought to show how to use
|
||||
Predis as it does not cover all of its features.
|
||||
|
||||
* [v0.8] Implement smart and transparent support for redis-cluster.
|
||||
* Add more tests targeting specific functions of the library.
|
||||
|
||||
* Missing tests for commands:
|
||||
PUBLISH, SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<?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__.'/lib/Predis/Autoloader.php';
|
||||
|
||||
Predis\Autoloader::register();
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?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.
|
||||
*/
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// In order to be able to execute this script to create a Phar archive of Predis,
|
||||
// the Phar module must be loaded and the "phar.readonly" directive php.ini must
|
||||
// be set to "off". You can change the values in the $options array to customize
|
||||
// the creation of the Phar archive to better suit your needs.
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
$options = array(
|
||||
'name' => 'predis',
|
||||
'project_path' => __DIR__ . '/../lib/',
|
||||
'compression' => Phar::NONE,
|
||||
'append_version' => true,
|
||||
);
|
||||
|
||||
function getPharFilename($options)
|
||||
{
|
||||
$filename = $options['name'];
|
||||
|
||||
// NOTE: do not consider "append_version" with Phar compression do to a bug in
|
||||
// Phar::compress() when renaming phar archives containing dots in their name.
|
||||
if ($options['append_version'] && $options['compression'] === Phar::NONE) {
|
||||
$versionFile = @fopen(__DIR__ . '/../VERSION', 'r');
|
||||
|
||||
if ($versionFile === false) {
|
||||
throw new Exception("Could not locate the VERSION file.");
|
||||
}
|
||||
|
||||
$version = trim(fgets($versionFile));
|
||||
fclose($versionFile);
|
||||
$filename .= "_$version";
|
||||
}
|
||||
|
||||
return "$filename.phar";
|
||||
}
|
||||
|
||||
function getPharStub($options)
|
||||
{
|
||||
return <<<EOSTUB
|
||||
<?php
|
||||
Phar::mapPhar('predis.phar');
|
||||
spl_autoload_register(function(\$class) {
|
||||
if (strpos(\$class, 'Predis\\\\') === 0) {
|
||||
\$file = 'phar://predis.phar/'.strtr(\$class, '\\\', '/').'.php';
|
||||
if (file_exists(\$file)) {
|
||||
require \$file;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
__HALT_COMPILER();
|
||||
EOSTUB;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
$phar = new Phar(getPharFilename($options));
|
||||
$phar->compress($options['compression']);
|
||||
$phar->setStub(getPharStub($options));
|
||||
$phar->buildFromDirectory($options['project_path']);
|
||||
@@ -1,605 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?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.
|
||||
*/
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// This script can be used to automatically glue all the .php files of Predis
|
||||
// into a single monolithic script file that can be used without an autoloader,
|
||||
// just like the other previous versions of the library.
|
||||
//
|
||||
// Much of its complexity is due to the fact that we cannot simply join PHP
|
||||
// files, but namespaces and classes definitions must follow a precise order
|
||||
// when dealing with subclassing and inheritance.
|
||||
//
|
||||
// The current implementation is pretty naïve, but it should do for now.
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
class CommandLine
|
||||
{
|
||||
public static function getOptions()
|
||||
{
|
||||
$parameters = array(
|
||||
's:' => 'source:',
|
||||
'o:' => 'output:',
|
||||
'e:' => 'exclude:',
|
||||
'E:' => 'exclude-classes:',
|
||||
);
|
||||
|
||||
$getops = getopt(implode(array_keys($parameters)), $parameters);
|
||||
|
||||
$options = array(
|
||||
'source' => __DIR__ . "/../lib/",
|
||||
'output' => PredisFile::NS_ROOT . '.php',
|
||||
'exclude' => array(),
|
||||
);
|
||||
|
||||
foreach ($getops as $option => $value) {
|
||||
switch ($option) {
|
||||
case 's':
|
||||
case 'source':
|
||||
$options['source'] = $value;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'output':
|
||||
$options['output'] = $value;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
case 'exclude-classes':
|
||||
$options['exclude'] = @file($value, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: $value;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'exclude':
|
||||
$options['exclude'] = is_array($value) ? $value : array($value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
|
||||
class PredisFile
|
||||
{
|
||||
const NS_ROOT = 'Predis';
|
||||
|
||||
private $namespaces;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->namespaces = array();
|
||||
}
|
||||
|
||||
public static function from($libraryPath, Array $exclude = array())
|
||||
{
|
||||
$nsroot = self::NS_ROOT;
|
||||
$predisFile = new PredisFile();
|
||||
$libIterator = new RecursiveDirectoryIterator("$libraryPath$nsroot");
|
||||
|
||||
foreach (new RecursiveIteratorIterator($libIterator) as $classFile)
|
||||
{
|
||||
if (!$classFile->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$namespace = strtr(str_replace($libraryPath, '', $classFile->getPath()), '/', '\\');
|
||||
|
||||
if (in_array(sprintf('%s\\%s', $namespace, $classFile->getBasename('.php')), $exclude)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$phpNamespace = $predisFile->getNamespace($namespace);
|
||||
|
||||
if ($phpNamespace === false) {
|
||||
$phpNamespace = new PhpNamespace($namespace);
|
||||
$predisFile->addNamespace($phpNamespace);
|
||||
}
|
||||
|
||||
$phpClass = new PhpClass($phpNamespace, $classFile);
|
||||
}
|
||||
|
||||
return $predisFile;
|
||||
}
|
||||
|
||||
public function addNamespace(PhpNamespace $namespace)
|
||||
{
|
||||
if (isset($this->namespaces[(string)$namespace])) {
|
||||
throw new InvalidArgumentException("Duplicated namespace");
|
||||
}
|
||||
$this->namespaces[(string)$namespace] = $namespace;
|
||||
}
|
||||
|
||||
public function getNamespaces()
|
||||
{
|
||||
return $this->namespaces;
|
||||
}
|
||||
|
||||
public function getNamespace($namespace)
|
||||
{
|
||||
if (!isset($this->namespaces[$namespace])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->namespaces[$namespace];
|
||||
}
|
||||
|
||||
public function getClassByFQN($classFqn)
|
||||
{
|
||||
if (($nsLastPos = strrpos($classFqn, '\\')) !== false) {
|
||||
$namespace = $this->getNamespace(substr($classFqn, 0, $nsLastPos));
|
||||
if ($namespace === false) {
|
||||
return null;
|
||||
}
|
||||
$className = substr($classFqn, $nsLastPos + 1);
|
||||
|
||||
return $namespace->getClass($className);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function calculateDependencyScores(&$classes, $fqn)
|
||||
{
|
||||
if (!isset($classes[$fqn])) {
|
||||
$classes[$fqn] = 0;
|
||||
}
|
||||
|
||||
$classes[$fqn] += 1;
|
||||
|
||||
if (($phpClass = $this->getClassByFQN($fqn)) === null) {
|
||||
throw new RuntimeException(
|
||||
"Cannot found the class $fqn which is required by other subclasses. Are you missing a file?"
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($phpClass->getDependencies() as $fqn) {
|
||||
$this->calculateDependencyScores($classes, $fqn);
|
||||
}
|
||||
}
|
||||
|
||||
private function getDependencyScores()
|
||||
{
|
||||
$classes = array();
|
||||
|
||||
foreach ($this->getNamespaces() as $phpNamespace) {
|
||||
foreach ($phpNamespace->getClasses() as $phpClass) {
|
||||
$this->calculateDependencyScores($classes, $phpClass->getFQN());
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
private function getOrderedNamespaces($dependencyScores)
|
||||
{
|
||||
$namespaces = array_fill_keys(array_unique(
|
||||
array_map(
|
||||
function($fqn) { return PhpNamespace::extractName($fqn); },
|
||||
array_keys($dependencyScores)
|
||||
)
|
||||
), 0);
|
||||
|
||||
foreach ($dependencyScores as $classFqn => $score) {
|
||||
$namespaces[PhpNamespace::extractName($classFqn)] += $score;
|
||||
}
|
||||
|
||||
arsort($namespaces);
|
||||
|
||||
return array_keys($namespaces);
|
||||
}
|
||||
|
||||
private function getOrderedClasses(PhpNamespace $phpNamespace, $classes)
|
||||
{
|
||||
$nsClassesFQNs = array_map(function($cl) { return $cl->getFQN(); }, $phpNamespace->getClasses());
|
||||
$nsOrderedClasses = array();
|
||||
|
||||
foreach ($nsClassesFQNs as $nsClassFQN) {
|
||||
$nsOrderedClasses[$nsClassFQN] = $classes[$nsClassFQN];
|
||||
}
|
||||
|
||||
arsort($nsOrderedClasses);
|
||||
|
||||
return array_keys($nsOrderedClasses);
|
||||
}
|
||||
|
||||
public function getPhpCode()
|
||||
{
|
||||
$buffer = array("<?php\n\n", PhpClass::LICENSE_HEADER, "\n\n");
|
||||
$classes = $this->getDependencyScores();
|
||||
$namespaces = $this->getOrderedNamespaces($classes);
|
||||
|
||||
foreach ($namespaces as $namespace) {
|
||||
$phpNamespace = $this->getNamespace($namespace);
|
||||
|
||||
// generate namespace directive
|
||||
$buffer[] = $phpNamespace->getPhpCode();
|
||||
$buffer[] = "\n";
|
||||
|
||||
// generate use directives
|
||||
$useDirectives = $phpNamespace->getUseDirectives();
|
||||
if (count($useDirectives) > 0) {
|
||||
$buffer[] = $useDirectives->getPhpCode();
|
||||
$buffer[] = "\n";
|
||||
}
|
||||
|
||||
// generate classes bodies
|
||||
$nsClasses = $this->getOrderedClasses($phpNamespace, $classes);
|
||||
foreach ($nsClasses as $classFQN) {
|
||||
$buffer[] = $this->getClassByFQN($classFQN)->getPhpCode();
|
||||
$buffer[] = "\n\n";
|
||||
}
|
||||
|
||||
$buffer[] = "/* " . str_repeat("-", 75) . " */";
|
||||
$buffer[] = "\n\n";
|
||||
}
|
||||
|
||||
return implode($buffer);
|
||||
}
|
||||
|
||||
public function saveTo($outputFile)
|
||||
{
|
||||
// TODO: add more sanity checks
|
||||
if ($outputFile === null || $outputFile === '') {
|
||||
throw new InvalidArgumentException('You must specify a valid output file');
|
||||
}
|
||||
file_put_contents($outputFile, $this->getPhpCode());
|
||||
}
|
||||
}
|
||||
|
||||
class PhpNamespace implements IteratorAggregate
|
||||
{
|
||||
private $namespace;
|
||||
private $classes;
|
||||
|
||||
public function __construct($namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->classes = array();
|
||||
$this->useDirectives = new PhpUseDirectives($this);
|
||||
}
|
||||
|
||||
public static function extractName($fqn)
|
||||
{
|
||||
$nsSepLast = strrpos($fqn, '\\');
|
||||
if ($nsSepLast === false) {
|
||||
return $fqn;
|
||||
}
|
||||
$ns = substr($fqn, 0, $nsSepLast);
|
||||
|
||||
return $ns !== '' ? $ns : null;
|
||||
}
|
||||
|
||||
public function addClass(PhpClass $class)
|
||||
{
|
||||
$this->classes[$class->getName()] = $class;
|
||||
}
|
||||
|
||||
public function getClass($className)
|
||||
{
|
||||
if (isset($this->classes[$className])) {
|
||||
return $this->classes[$className];
|
||||
}
|
||||
}
|
||||
|
||||
public function getClasses()
|
||||
{
|
||||
return array_values($this->classes);
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->getClasses());
|
||||
}
|
||||
|
||||
public function getUseDirectives()
|
||||
{
|
||||
return $this->useDirectives;
|
||||
}
|
||||
|
||||
public function getPhpCode()
|
||||
{
|
||||
return "namespace $this->namespace;\n";
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
}
|
||||
|
||||
class PhpUseDirectives implements Countable, IteratorAggregate
|
||||
{
|
||||
private $use;
|
||||
private $aliases;
|
||||
private $namespace;
|
||||
|
||||
public function __construct(PhpNamespace $namespace)
|
||||
{
|
||||
$this->use = array();
|
||||
$this->aliases = array();
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
public function add($use, $as = null)
|
||||
{
|
||||
if (in_array($use, $this->use)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->use[] = $use;
|
||||
$this->aliases[$as ?: PhpClass::extractName($use)] = $use;
|
||||
}
|
||||
|
||||
public function getList()
|
||||
{
|
||||
return $this->use;
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->getList());
|
||||
}
|
||||
|
||||
public function getPhpCode()
|
||||
{
|
||||
$reducer = function($str, $use) { return $str .= "use $use;\n"; };
|
||||
|
||||
return array_reduce($this->getList(), $reducer, '');
|
||||
}
|
||||
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
public function getFQN($className)
|
||||
{
|
||||
if (($nsSepFirst = strpos($className, '\\')) === false) {
|
||||
if (isset($this->aliases[$className])) {
|
||||
return $this->aliases[$className];
|
||||
}
|
||||
|
||||
return (string)$this->getNamespace() . "\\$className";
|
||||
}
|
||||
|
||||
if ($nsSepFirst != 0) {
|
||||
throw new InvalidArgumentException("Partially qualified names are not supported");
|
||||
}
|
||||
|
||||
return $className;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->use);
|
||||
}
|
||||
}
|
||||
|
||||
class PhpClass
|
||||
{
|
||||
const LICENSE_HEADER = <<<LICENSE
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
LICENSE;
|
||||
|
||||
private $namespace;
|
||||
private $file;
|
||||
private $body;
|
||||
private $implements;
|
||||
private $extends;
|
||||
private $name;
|
||||
|
||||
public function __construct(PhpNamespace $namespace, SplFileInfo $classFile)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->file = $classFile;
|
||||
$this->implements = array();
|
||||
$this->extends = array();
|
||||
|
||||
$this->extractData();
|
||||
$namespace->addClass($this);
|
||||
}
|
||||
|
||||
public static function extractName($fqn)
|
||||
{
|
||||
$nsSepLast = strrpos($fqn, '\\');
|
||||
if ($nsSepLast === false) {
|
||||
return $fqn;
|
||||
}
|
||||
|
||||
return substr($fqn, $nsSepLast + 1);
|
||||
}
|
||||
|
||||
private function extractData()
|
||||
{
|
||||
$useDirectives = $this->getNamespace()->getUseDirectives();
|
||||
|
||||
$useExtractor = function($m) use($useDirectives) {
|
||||
$useDirectives->add(($namespacedPath = $m[1]));
|
||||
};
|
||||
|
||||
$classBuffer = stream_get_contents(fopen($this->getFile()->getPathname(), 'r'));
|
||||
|
||||
$classBuffer = str_replace(self::LICENSE_HEADER, '', $classBuffer);
|
||||
|
||||
$classBuffer = preg_replace('/<\?php\s?\\n\s?/', '', $classBuffer);
|
||||
$classBuffer = preg_replace('/\s?\?>\n?/ms', '', $classBuffer);
|
||||
$classBuffer = preg_replace('/namespace\s+[\w\d_\\\\]+;\s?/', '', $classBuffer);
|
||||
$classBuffer = preg_replace_callback('/use\s+([\w\d_\\\\]+)(\s+as\s+.*)?;\s?\n?/', $useExtractor, $classBuffer);
|
||||
|
||||
$this->body = trim($classBuffer);
|
||||
|
||||
$this->extractHierarchy();
|
||||
}
|
||||
|
||||
private function extractHierarchy()
|
||||
{
|
||||
$implements = array();
|
||||
$extends = array();
|
||||
|
||||
$extractor = function($iterator, $callback) {
|
||||
$className = '';
|
||||
$iterator->seek($iterator->key() + 1);
|
||||
|
||||
while ($iterator->valid()) {
|
||||
$token = $iterator->current();
|
||||
|
||||
if (is_string($token)) {
|
||||
if (preg_match('/\s?,\s?/', $token)) {
|
||||
$callback(trim($className));
|
||||
$className = '';
|
||||
}
|
||||
else if ($token == '{') {
|
||||
$callback(trim($className));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($token[0]) {
|
||||
case T_NS_SEPARATOR:
|
||||
$className .= '\\';
|
||||
break;
|
||||
|
||||
case T_STRING:
|
||||
$className .= $token[1];
|
||||
break;
|
||||
|
||||
case T_IMPLEMENTS:
|
||||
case T_EXTENDS:
|
||||
$callback(trim($className));
|
||||
$iterator->seek($iterator->key() - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
};
|
||||
|
||||
$tokens = token_get_all("<?php\n" . trim($this->getPhpCode()));
|
||||
$iterator = new ArrayIterator($tokens);
|
||||
|
||||
while ($iterator->valid()) {
|
||||
$token = $iterator->current();
|
||||
if (is_string($token)) {
|
||||
$iterator->next();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($token[0]) {
|
||||
case T_CLASS:
|
||||
case T_INTERFACE:
|
||||
$iterator->seek($iterator->key() + 2);
|
||||
$tk = $iterator->current();
|
||||
$this->name = $tk[1];
|
||||
break;
|
||||
|
||||
case T_IMPLEMENTS:
|
||||
$extractor($iterator, function($fqn) use (&$implements) {
|
||||
$implements[] = $fqn;
|
||||
});
|
||||
break;
|
||||
|
||||
case T_EXTENDS:
|
||||
$extractor($iterator, function($fqn) use (&$extends) {
|
||||
$extends[] = $fqn;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
$this->implements = $this->guessFQN($implements);
|
||||
$this->extends = $this->guessFQN($extends);
|
||||
}
|
||||
|
||||
public function guessFQN($classes)
|
||||
{
|
||||
$useDirectives = $this->getNamespace()->getUseDirectives();
|
||||
return array_map(array($useDirectives, 'getFQN'), $classes);
|
||||
}
|
||||
|
||||
public function getImplementedInterfaces($all = false)
|
||||
{
|
||||
if ($all) {
|
||||
return $this->implements;
|
||||
}
|
||||
|
||||
return array_filter(
|
||||
$this->implements,
|
||||
function ($cn) { return strpos($cn, 'Predis\\') === 0; }
|
||||
);
|
||||
}
|
||||
|
||||
public function getExtendedClasses($all = false)
|
||||
{
|
||||
if ($all) {
|
||||
return $this->extemds;
|
||||
}
|
||||
|
||||
return array_filter(
|
||||
$this->extends,
|
||||
function ($cn) { return strpos($cn, 'Predis\\') === 0; }
|
||||
);
|
||||
}
|
||||
|
||||
public function getDependencies($all = false)
|
||||
{
|
||||
return array_merge(
|
||||
$this->getImplementedInterfaces($all),
|
||||
$this->getExtendedClasses($all)
|
||||
);
|
||||
}
|
||||
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
public function getFile()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getFQN()
|
||||
{
|
||||
return (string)$this->getNamespace() . '\\' . $this->name;
|
||||
}
|
||||
|
||||
public function getPhpCode()
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return "class " . $this->getName() . '{ ... }';
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
$options = CommandLine::getOptions();
|
||||
$predisFile = PredisFile::from($options['source'], $options['exclude']);
|
||||
$predisFile->saveTo($options['output']);
|
||||
@@ -1,260 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?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.
|
||||
*/
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// This script can be used to automatically generate a file with the scheleton
|
||||
// of a test case to test a Redis command by specifying the name of the class
|
||||
// in the Predis\Commands namespace (only classes in this namespace are valid).
|
||||
// For example, to generate a test case for SET (which is represented by the
|
||||
// Predis\Commands\StringSet class):
|
||||
//
|
||||
// $ ./bin/generate-command-test.php --class=StringSet
|
||||
//
|
||||
// Here is a list of optional arguments:
|
||||
//
|
||||
// --realm: each command has its own realm (commands that operate on strings,
|
||||
// lists, sets and such) but while this realm is usually inferred from the name
|
||||
// of the specified class, sometimes it can be useful to override it with a
|
||||
// custom one.
|
||||
//
|
||||
// --output: write the generated test case to the specified path instead of
|
||||
// the default one.
|
||||
//
|
||||
// --overwrite: pre-existing test files are not overwritten unless this option
|
||||
// is explicitly specified.
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
use Predis\Commands\ICommand;
|
||||
use Predis\Commands\IPrefixable;
|
||||
|
||||
class CommandTestCaseGenerator
|
||||
{
|
||||
private $options;
|
||||
|
||||
public function __construct(Array $options)
|
||||
{
|
||||
if (!isset($options['class'])) {
|
||||
throw new RuntimeException("Missing 'class' option.");
|
||||
}
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public static function fromCommandLine()
|
||||
{
|
||||
$parameters = array(
|
||||
'c:' => 'class:',
|
||||
'r::' => 'realm::',
|
||||
'o::' => 'output::',
|
||||
'x::' => 'overwrite::'
|
||||
);
|
||||
|
||||
$getops = getopt(implode(array_keys($parameters)), $parameters);
|
||||
|
||||
$options = array(
|
||||
'overwrite' => false,
|
||||
'tests' => __DIR__.'/../tests',
|
||||
);
|
||||
|
||||
foreach ($getops as $option => $value) {
|
||||
switch ($option) {
|
||||
case 'c':
|
||||
case 'class':
|
||||
$options['class'] = $value;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'realm':
|
||||
$options['realm'] = $value;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'output':
|
||||
$options['output'] = $value;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'overwrite':
|
||||
$options['overwrite'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($options['class'])) {
|
||||
throw new RuntimeException("Missing 'class' option.");
|
||||
}
|
||||
|
||||
$options['fqn'] = "Predis\\Commands\\{$options['class']}";
|
||||
$options['path'] = "Predis/Commands/{$options['class']}.php";
|
||||
|
||||
$source = __DIR__.'/../lib/'.$options['path'];
|
||||
if (!file_exists($source)) {
|
||||
throw new RuntimeException("Cannot find class file for {$options['fqn']} in $source.");
|
||||
}
|
||||
|
||||
if (!isset($options['output'])) {
|
||||
$options['output'] = sprintf("%s/%s", $options['tests'], str_replace('.php', 'Test.php', $options['path']));
|
||||
}
|
||||
|
||||
return new self($options);
|
||||
}
|
||||
|
||||
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'];
|
||||
}
|
||||
|
||||
$class = array_pop(explode('\\', $this->options['fqn']));
|
||||
list($realm,) = preg_split('/([[:upper:]][[:lower:]]+)/', $class, 2, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
return strtolower($realm);
|
||||
}
|
||||
|
||||
public function generate()
|
||||
{
|
||||
$reflection = new ReflectionClass($class = $this->options['fqn']);
|
||||
|
||||
if (!$reflection->isInstantiable()) {
|
||||
throw new RuntimeException("Class $class must be instantiable, abstract classes or interfaces are not allowed.");
|
||||
}
|
||||
if (!$reflection->implementsInterface('Predis\Commands\ICommand')) {
|
||||
throw new RuntimeException("Class $class must implement the Predis\Commands\ICommand interface.");
|
||||
}
|
||||
|
||||
$instance = $reflection->newInstance();
|
||||
$buffer = $this->getTestCaseBuffer($instance);
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$options = $this->options;
|
||||
if (file_exists($options['output']) && !$options['overwrite']) {
|
||||
throw new RuntimeException("File {$options['output']} already exist. Specify the --overwrite option to overwrite the existing file.");
|
||||
}
|
||||
file_put_contents($options['output'], $this->generate());
|
||||
}
|
||||
|
||||
protected function getTestCaseBuffer(ICommand $instance)
|
||||
{
|
||||
$id = $instance->getId();
|
||||
$fqn = get_class($instance);
|
||||
$class = array_pop(explode('\\', $fqn)) . "Test";
|
||||
$realm = $this->getTestRealm();
|
||||
|
||||
$buffer =<<<PHP
|
||||
<?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\Commands;
|
||||
|
||||
use \PHPUnit_Framework_TestCase as StandardTestCase;
|
||||
|
||||
/**
|
||||
* @group commands
|
||||
* @group realm-$realm
|
||||
*/
|
||||
class $class extends CommandTestCase
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCommand()
|
||||
{
|
||||
return '$fqn';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedId()
|
||||
{
|
||||
return '$id';
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArguments()
|
||||
{
|
||||
\$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
|
||||
\$arguments = array(/* add arguments */);
|
||||
\$expected = array(/* add arguments */);
|
||||
|
||||
\$command = \$this->getCommand();
|
||||
\$command->setArguments(\$arguments);
|
||||
|
||||
\$this->assertSame(\$expected, \$command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParseResponse()
|
||||
{
|
||||
\$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
|
||||
\$raw = null;
|
||||
\$expected = null;
|
||||
|
||||
\$command = \$this->getCommand();
|
||||
|
||||
\$this->assertSame(\$expected, \$command->parseResponse(\$raw));
|
||||
}
|
||||
|
||||
PHP;
|
||||
|
||||
if ($instance instanceof IPrefixable) {
|
||||
$buffer .=<<<PHP
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testPrefixKeys()
|
||||
{
|
||||
\$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
|
||||
\$arguments = array(/* add arguments */);
|
||||
\$expected = array(/* add arguments */);
|
||||
|
||||
\$command = \$this->getCommandWithArgumentsArray(\$arguments);
|
||||
\$command->prefixKeys('prefix:');
|
||||
|
||||
\$this->assertSame(\$expected, \$command->getArguments());
|
||||
}
|
||||
|
||||
PHP;
|
||||
}
|
||||
|
||||
return "$buffer}\n";
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
require __DIR__.'/../autoload.php';
|
||||
|
||||
$generator = CommandTestCaseGenerator::fromCommandLine();
|
||||
$generator->save();
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"type": "library",
|
||||
"description": "Flexible and feature-complete PHP client library for Redis",
|
||||
"keywords": ["nosql", "redis", "predis"],
|
||||
"homepage": "http://github.com/nrk/predis",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daniele Alessandri",
|
||||
"email": "suppakilla@gmail.com",
|
||||
"homepage": "http://clorophilla.net"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {"Predis": "lib/"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
require_once 'SharedConfigurations.php';
|
||||
|
||||
// When you have a whole set of consecutive commands to send to
|
||||
// a redis server, you can use a pipeline to improve performances.
|
||||
|
||||
$redis = new Predis_Client($single_server);
|
||||
|
||||
$pipe = $redis->pipeline();
|
||||
$pipe->ping();
|
||||
$pipe->flushdb();
|
||||
$pipe->incrby('counter', 10);
|
||||
$pipe->incrby('counter', 30);
|
||||
$pipe->exists('counter');
|
||||
$pipe->get('counter');
|
||||
$pipe->mget('does_not_exist', 'counter');
|
||||
$replies = $pipe->execute();
|
||||
|
||||
print_r($replies);
|
||||
|
||||
/* OUTPUT:
|
||||
Array
|
||||
(
|
||||
[0] => 1
|
||||
[1] => 1
|
||||
[2] => 10
|
||||
[3] => 40
|
||||
[4] => 1
|
||||
[5] => 40
|
||||
[6] => Array
|
||||
(
|
||||
[0] =>
|
||||
[1] => 40
|
||||
)
|
||||
|
||||
)
|
||||
*/
|
||||
?>
|
||||
@@ -1,82 +1,68 @@
|
||||
<?php
|
||||
require_once 'SharedConfigurations.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.
|
||||
*/
|
||||
// Developers can customize the distribution strategy used by the client
|
||||
// to distribute keys among a cluster of servers simply by creating a class
|
||||
// that implements the Predis_Distribution_IDistributionAlgorithm interface.
|
||||
|
||||
require 'SharedConfigurations.php';
|
||||
class NaiveDistributionStrategy
|
||||
implements Predis_Distribution_IDistributionStrategy {
|
||||
|
||||
// Developers can customize the distribution strategy used by the client
|
||||
// to distribute keys among a cluster of servers simply by creating a class
|
||||
// that implements the Predis\Distribution\IDistributionStrategy interface.
|
||||
private $_nodes, $_nodesCount;
|
||||
|
||||
use Predis\Distribution\IDistributionStrategy;
|
||||
use Predis\Network\PredisCluster;
|
||||
|
||||
class NaiveDistributionStrategy implements IDistributionStrategy
|
||||
{
|
||||
private $nodes;
|
||||
private $nodesCount;
|
||||
|
||||
public function __constructor()
|
||||
{
|
||||
$this->nodes = array();
|
||||
$this->nodesCount = 0;
|
||||
public function __constructor() {
|
||||
$this->_nodes = array();
|
||||
$this->_nodesCount = 0;
|
||||
}
|
||||
|
||||
public function add($node, $weight = null)
|
||||
{
|
||||
$this->nodes[] = $node;
|
||||
$this->nodesCount++;
|
||||
public function add($node, $weight = null) {
|
||||
$this->_nodes[] = $node;
|
||||
$this->_nodesCount++;
|
||||
}
|
||||
|
||||
public function remove($node)
|
||||
{
|
||||
$this->nodes = array_filter($this->nodes, function($n) use($node) {
|
||||
return $n !== $node;
|
||||
});
|
||||
|
||||
$this->nodesCount = count($this->nodes);
|
||||
private static function array_remove($array, $value) {
|
||||
$newArray = array();
|
||||
foreach ($array as $k => $v) {
|
||||
if ($v !== $value) {
|
||||
$newArray[] = $v;
|
||||
}
|
||||
}
|
||||
return $newArray;
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$count = $this->nodesCount;
|
||||
public function remove($node) {
|
||||
$this->_nodes = self::array_remove($this->_nodes, $node);
|
||||
$this->_nodesCount = count($this->_nodes);
|
||||
}
|
||||
|
||||
public function get($key) {
|
||||
$count = $this->_nodesCount;
|
||||
if ($count === 0) {
|
||||
throw new RuntimeException('No connections');
|
||||
}
|
||||
|
||||
return $this->nodes[$count > 1 ? abs(crc32($key) % $count) : 0];
|
||||
return $this->_nodes[$count > 1 ? abs(crc32($key) % $count) : 0];
|
||||
}
|
||||
|
||||
public function generateKey($value)
|
||||
{
|
||||
public function generateKey($value) {
|
||||
return crc32($value);
|
||||
}
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'cluster' => function() {
|
||||
$distributor = new NaiveDistributionStrategy();
|
||||
return new PredisCluster($distributor);
|
||||
},
|
||||
'key_distribution' => new NaiveDistributionStrategy(),
|
||||
);
|
||||
|
||||
$client = new Predis\Client($multiple_servers, $options);
|
||||
$redis = new Predis_Client($multiple_servers, $options);
|
||||
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$client->set("key:$i", str_pad($i, 4, '0', 0));
|
||||
$client->get("key:$i");
|
||||
$redis->set("key:$i", str_pad($i, 4, '0', 0));
|
||||
$redis->get("key:$i");
|
||||
}
|
||||
|
||||
$server1 = $client->getClientFor('first')->info();
|
||||
$server2 = $client->getClientFor('second')->info();
|
||||
$server1 = $redis->getClientFor('first')->info();
|
||||
$server2 = $redis->getClientFor('second')->info();
|
||||
|
||||
printf("Server '%s' has %d keys while server '%s' has %d keys.\n",
|
||||
printf("Server '%s' has %d keys while server '%s' has %d keys.\n",
|
||||
'first', $server1['db15']['keys'], 'second', $server2['db15']['keys']
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
/*
|
||||
This is a basic example on how to use the Predis\DispatcherLoop class.
|
||||
|
||||
To see this example in action you can just use redis-cli and publish some
|
||||
messages to the 'events' and 'control' channel, e.g.:
|
||||
|
||||
./redis-cli
|
||||
PUBLISH events first
|
||||
PUBLISH events second
|
||||
PUBLISH events third
|
||||
PUBLISH control terminate_dispatcher
|
||||
*/
|
||||
|
||||
// Create a client and disable r/w timeout on the socket
|
||||
$client = new Predis\Client($single_server + array('read_write_timeout' => 0));
|
||||
|
||||
// Create a Predis\DispatcherLoop instance and attach a bunch of callbacks.
|
||||
$dispatcher = new Predis\PubSub\DispatcherLoop($client);
|
||||
|
||||
// Demonstrate how to use a callable class as a callback for Predis\DispatcherLoop.
|
||||
class EventsListener implements Countable
|
||||
{
|
||||
private $events;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->events = array();
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->events);
|
||||
}
|
||||
|
||||
public function getEvents()
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
public function __invoke($payload)
|
||||
{
|
||||
$this->events[] = $payload;
|
||||
}
|
||||
}
|
||||
|
||||
// Attach our callable class to the dispatcher.
|
||||
$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) {
|
||||
if ($payload === 'terminate_dispatcher') {
|
||||
$dispatcher->stop();
|
||||
}
|
||||
});
|
||||
|
||||
// Run the dispatcher loop until the callback attached to the 'control' channel
|
||||
// receives 'terminate_dispatcher' as a message.
|
||||
$dispatcher->run();
|
||||
|
||||
// Display our achievements!
|
||||
echo "We received {$events->count()} messages!\n";
|
||||
|
||||
// Say goodbye :-)
|
||||
$info = $client->info();
|
||||
print_r("Goodbye from Redis v{$info['redis_version']}!\n");
|
||||
@@ -1,37 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
// Predis ships with a KeyPrefixProcessor class that is used to transparently
|
||||
// prefix each key before sending commands to Redis, even for complex commands
|
||||
// such as SORT, ZUNIONSTORE and ZINTERSTORE. Key prefixes are useful to create
|
||||
// user-level namespaces for you keyspace, thus eliminating the need for separate
|
||||
// logical databases.
|
||||
|
||||
$client = new Predis\Client($single_server, array('prefix' => 'nrk:'));
|
||||
|
||||
$client->mset(array('foo' => 'bar', 'lol' => 'wut'));
|
||||
var_dump($client->mget('foo', 'lol'));
|
||||
/*
|
||||
array(2) {
|
||||
[0]=> string(3) "bar"
|
||||
[1]=> string(3) "wut"
|
||||
}
|
||||
*/
|
||||
|
||||
var_dump($client->keys('*'));
|
||||
/*
|
||||
array(2) {
|
||||
[0]=> string(7) "nrk:foo"
|
||||
[1]=> string(7) "nrk:lol"
|
||||
}
|
||||
*/
|
||||
@@ -1,52 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
// Predis supports master / slave replication scenarios where write operations are
|
||||
// performed on the master server and read operations are executed against one of
|
||||
// the slaves. The behaviour of commands or EVAL scripts can be customized at will.
|
||||
// As soon as a write operation is performed, all the subsequent requests (reads
|
||||
// or writes) will be served by the master server.
|
||||
//
|
||||
// This example must be executed with the second Redis server acting as the slave
|
||||
// of the first one using the SLAVEOF command.
|
||||
//
|
||||
|
||||
$parameters = array(
|
||||
'tcp://127.0.0.1:6379?database=15&alias=master',
|
||||
'tcp://127.0.0.1:6380?database=15&alias=slave',
|
||||
);
|
||||
|
||||
$options = array('replication' => true);
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
|
||||
// Read operation.
|
||||
$exists = $client->exists('foo') ? 'yes' : 'no';
|
||||
$current = $client->getConnection()->getCurrent()->getParameters();
|
||||
echo "Does 'foo' exist on {$current->alias}? $exists.\n";
|
||||
|
||||
// Write operation.
|
||||
$client->set('foo', 'bar');
|
||||
$current = $client->getConnection()->getCurrent()->getParameters();
|
||||
echo "Now 'foo' has been set to 'bar' on {$current->alias}!\n";
|
||||
|
||||
// Read operation.
|
||||
$bar = $client->get('foo');
|
||||
$current = $client->getConnection()->getCurrent()->getParameters();
|
||||
echo "We just fetched 'foo' from {$current->alias} and its value is '$bar'.\n";
|
||||
|
||||
/* OUTPUT:
|
||||
Does 'foo' exist on slave? yes.
|
||||
Now 'foo' has been set to 'bar' on master!
|
||||
We just fetched 'foo' from master and its value is 'bar'.
|
||||
*/
|
||||
@@ -1,81 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
// Predis allows to set Lua scripts as read-only operations in the context of
|
||||
// replication. This works for both EVAL and EVALSHA and also for the client-side
|
||||
// abstraction built upon them (Predis\Commands\ScriptedCommand). This example
|
||||
// shows a slightly more complex configuration that injects a new scripted 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.
|
||||
|
||||
use Predis\Profiles\ServerProfile;
|
||||
use Predis\Commands\ScriptedCommand;
|
||||
use Predis\Network\MasterSlaveReplication;
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
// Define a new scripted command that returns all the fields
|
||||
// of a variable number of hashes with a single roundtrip.
|
||||
|
||||
class HashMultipleGetAll extends ScriptedCommand {
|
||||
const BODY = <<<EOS
|
||||
local hashes = {}
|
||||
for _, key in pairs(KEYS) do
|
||||
table.insert(hashes, key)
|
||||
table.insert(hashes, redis.call('hgetall', key))
|
||||
end
|
||||
return hashes
|
||||
EOS;
|
||||
|
||||
public function getScript() {
|
||||
return self::BODY;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
$parameters = array(
|
||||
'tcp://127.0.0.1:6379/?alias=master',
|
||||
'tcp://127.0.0.1:6380/?alias=slave',
|
||||
);
|
||||
|
||||
$options = array(
|
||||
'profile' => function($options) {
|
||||
$profile = ServerProfile::get('dev');
|
||||
$profile->defineCommand('hmgetall', 'HashMultipleGetAll');
|
||||
|
||||
return $profile;
|
||||
},
|
||||
'replication' => function($options) {
|
||||
$replication = new MasterSlaveReplication();
|
||||
$replication->setScriptReadOnly(HashMultipleGetAll::BODY);
|
||||
|
||||
return $replication;
|
||||
},
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
$client = new Predis\Client($parameters, $options);
|
||||
|
||||
// Execute the following commands on the master server using redis-cli:
|
||||
// $ ./redis-cli HMSET metavars foo bar hoge piyo
|
||||
// $ ./redis-cli HMSET servers master host1 slave host2
|
||||
|
||||
$hashes = $client->hmgetall('metavars', 'servers');
|
||||
|
||||
$replication = $client->getConnection();
|
||||
$stillOnSlave = $replication->getCurrent() === $replication->getConnectionById('slave');
|
||||
|
||||
echo "Is still on slave? ", $stillOnSlave ? 'YES' : 'NO', "!\n";
|
||||
var_export($hashes);
|
||||
@@ -1,44 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
// This is a basic example on how to use the Predis\MonitorContext class.
|
||||
// You can use redis-cli to send commands to the same Redis instance your client is
|
||||
// connected to, and then type "ECHO QUIT_MONITOR" in redis-cli when you want to
|
||||
// exit the monitor loop and terminate this script in a graceful way.
|
||||
|
||||
// Create a client and disable r/w timeout on the socket.
|
||||
$client = new Predis\Client($single_server + array('read_write_timeout' => 0));
|
||||
|
||||
// Use only one instance of DateTime, we will update the timestamp later.
|
||||
$timestamp = new DateTime();
|
||||
|
||||
foreach (($monitor = $client->monitor()) as $event) {
|
||||
$timestamp->setTimestamp((int) $event->timestamp);
|
||||
|
||||
// If we notice a ECHO command with the message QUIT_MONITOR, we close the
|
||||
// monitor context and then break the loop.
|
||||
if ($event->command === 'ECHO' && $event->arguments === '"QUIT_MONITOR"') {
|
||||
echo "Exiting the monitor loop...\n";
|
||||
$monitor->closeContext();
|
||||
break;
|
||||
}
|
||||
|
||||
echo "* Received {$event->command} on DB {$event->database} at {$timestamp->format(DateTime::W3C)}\n";
|
||||
if (isset($event->arguments)) {
|
||||
echo " Arguments: {$event->arguments}\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Say goodbye :-)
|
||||
$info = $client->info();
|
||||
print_r("Goodbye from Redis v{$info['redis_version']}!\n");
|
||||
@@ -1,51 +1,38 @@
|
||||
<?php
|
||||
require_once 'SharedConfigurations.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.
|
||||
*/
|
||||
This is an implementation of an atomic client-side ZPOP using the support for
|
||||
check-and-set (CAS) operations with MULTI/EXEC transactions, as described in
|
||||
"WATCH explained" from http://redis.io/topics/transactions
|
||||
|
||||
require 'SharedConfigurations.php';
|
||||
First, populate your database with a tiny sample data set:
|
||||
|
||||
// This is an implementation of an atomic client-side ZPOP using the support for
|
||||
// check-and-set (CAS) operations with MULTI/EXEC transactions, as described in
|
||||
// "WATCH explained" from http://redis.io/topics/transactions
|
||||
//
|
||||
// First, populate your database with a tiny sample data set:
|
||||
//
|
||||
// ./redis-cli
|
||||
// SELECT 15
|
||||
// ZADD zset 1 a
|
||||
// ZADD zset 2 b
|
||||
// ZADD zset 3 c
|
||||
./redis-cli
|
||||
SELECT 15
|
||||
ZADD zset 1 a
|
||||
ZADD zset 2 b
|
||||
ZADD zset 3 c
|
||||
*/
|
||||
|
||||
function zpop($client, $key)
|
||||
{
|
||||
function zpop($client, $zsetKey) {
|
||||
$element = null;
|
||||
$options = array(
|
||||
'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.
|
||||
'cas' => true, // Initialize with support for CAS operations
|
||||
'watch' => $zsetKey, // Key that needs to be WATCHed to detect changes
|
||||
);
|
||||
|
||||
$client->multiExec($options, function($tx) use ($key, &$element) {
|
||||
@list($element) = $tx->zrange($key, 0, 0);
|
||||
|
||||
if (isset($element)) {
|
||||
$tx->multi(); // With CAS, MULTI *must* be explicitly invoked.
|
||||
$tx->zrem($key, $element);
|
||||
}
|
||||
});
|
||||
|
||||
$tx = $client->multiExec($options);
|
||||
@list($element) = $tx->zrange($zsetKey, 0, 0);
|
||||
if (isset($element)) {
|
||||
$tx->multi(); // With CAS, MULTI *must* be explicitly invoked.
|
||||
$tx->zrem($zsetKey, $element);
|
||||
$tx->exec();
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
$client = new Predis\Client($single_server);
|
||||
$zpopped = zpop($client, 'zset');
|
||||
|
||||
$redis = new Predis_Client($single_server, 'dev');
|
||||
$zpopped = zpop($redis, 'zset');
|
||||
echo isset($zpopped) ? "ZPOPed $zpopped" : "Nothing to ZPOP!", "\n";
|
||||
?>
|
||||
|
||||
@@ -1,30 +1,20 @@
|
||||
<?php
|
||||
require_once 'SharedConfigurations.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 'SharedConfigurations.php';
|
||||
|
||||
// redis can set keys and their relative values in one go
|
||||
// using MSET, then the same values can be retrieved with
|
||||
// redis can set keys and their relative values in one go
|
||||
// using MSET, then the same values can be retrieved with
|
||||
// a single command using MGET.
|
||||
|
||||
$mkv = array(
|
||||
'usr:0001' => 'First user',
|
||||
'usr:0002' => 'Second user',
|
||||
'usr:0003' => 'Third user'
|
||||
'usr:0002' => 'Second user',
|
||||
'usr:0003' => 'Third user'
|
||||
);
|
||||
|
||||
$client = new Predis\Client($single_server);
|
||||
$redis = new Predis_Client($single_server);
|
||||
|
||||
$client->mset($mkv);
|
||||
$retval = $client->mget(array_keys($mkv));
|
||||
$redis->mset($mkv);
|
||||
$retval = $redis->mget(array_keys($mkv));
|
||||
|
||||
print_r($retval);
|
||||
|
||||
@@ -36,3 +26,4 @@ Array
|
||||
[2] => Third user
|
||||
)
|
||||
*/
|
||||
?>
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
// When you have a whole set of consecutive commands to send to
|
||||
// a redis server, you can use a pipeline to improve performances.
|
||||
|
||||
$client = new Predis\Client($single_server);
|
||||
|
||||
$replies = $client->pipeline(function($pipe) {
|
||||
$pipe->ping();
|
||||
$pipe->flushdb();
|
||||
$pipe->incrby('counter', 10);
|
||||
$pipe->incrby('counter', 30);
|
||||
$pipe->exists('counter');
|
||||
$pipe->get('counter');
|
||||
$pipe->mget('does_not_exist', 'counter');
|
||||
});
|
||||
|
||||
print_r($replies);
|
||||
|
||||
/* OUTPUT:
|
||||
Array
|
||||
(
|
||||
[0] => 1
|
||||
[1] => 1
|
||||
[2] => 10
|
||||
[3] => 40
|
||||
[4] => 1
|
||||
[5] => 40
|
||||
[6] => Array
|
||||
(
|
||||
[0] =>
|
||||
[1] => 40
|
||||
)
|
||||
|
||||
)
|
||||
*/
|
||||
+11
-20
@@ -1,29 +1,20 @@
|
||||
<?php
|
||||
require_once 'SharedConfigurations.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 'SharedConfigurations.php';
|
||||
|
||||
// Redis 2.0 features new commands that allow clients to subscribe for
|
||||
// Redis 2.0 features new commands that allow clients to subscribe for
|
||||
// events published on certain channels (PUBSUB).
|
||||
|
||||
// Create a client and disable r/w timeout on the socket
|
||||
$client = new Predis\Client($single_server + array('read_write_timeout' => 0));
|
||||
$redis = new Predis_Client($single_server + array('read_write_timeout' => -1));
|
||||
|
||||
// Initialize a new pubsub context
|
||||
$pubsub = $client->pubSub();
|
||||
$pubsub = $redis->pubSubContext();
|
||||
|
||||
// Subscribe to your channels
|
||||
$pubsub->subscribe('control_channel', 'notifications');
|
||||
$pubsub->subscribe('control_channel');
|
||||
$pubsub->subscribe('notifications');
|
||||
|
||||
// Start processing the pubsup messages. Open a terminal and use redis-cli
|
||||
// Start processing the pubsup messages. Open a terminal and use redis-cli
|
||||
// to push messages to the channels. Examples:
|
||||
// ./redis-cli PUBLISH notifications "this is a test"
|
||||
// ./redis-cli PUBLISH control_channel quit_loop
|
||||
@@ -32,7 +23,6 @@ foreach ($pubsub as $message) {
|
||||
case 'subscribe':
|
||||
echo "Subscribed to {$message->channel}\n";
|
||||
break;
|
||||
|
||||
case 'message':
|
||||
if ($message->channel == 'control_channel') {
|
||||
if ($message->payload == 'quit_loop') {
|
||||
@@ -51,11 +41,12 @@ foreach ($pubsub as $message) {
|
||||
}
|
||||
}
|
||||
|
||||
// Always unset the pubsub context instance when you are done! The
|
||||
// class destructor will take care of cleanups and prevent protocol
|
||||
// Always unset the pubsub context instance when you are done! The
|
||||
// class destructor will take care of cleanups and prevent protocol
|
||||
// desynchronizations between the client and the server.
|
||||
unset($pubsub);
|
||||
|
||||
// Say goodbye :-)
|
||||
$info = $client->info();
|
||||
$info = $redis->info();
|
||||
print_r("Goodbye from Redis v{$info['redis_version']}!\n");
|
||||
?>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
// This example will not work with versions of Redis < 2.6.
|
||||
//
|
||||
// Additionally to the EVAL command defined in the current development profile, the new
|
||||
// Predis\Commands\ScriptedCommand base class can be used to build an higher abstraction
|
||||
// for our "scripted" commands so that they will appear just like any other command on
|
||||
// the client-side. This is a quick example used to implement INCREX.
|
||||
|
||||
use Predis\Commands\ScriptedCommand;
|
||||
|
||||
class IncrementExistingKey extends ScriptedCommand
|
||||
{
|
||||
public function getKeysCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getScript()
|
||||
{
|
||||
return
|
||||
<<<LUA
|
||||
local cmd = redis.call
|
||||
if cmd('exists', KEYS[1]) == 1 then
|
||||
return cmd('incr', KEYS[1])
|
||||
end
|
||||
LUA;
|
||||
}
|
||||
}
|
||||
|
||||
$client = new Predis\Client($single_server, 'dev');
|
||||
|
||||
$client->getProfile()->defineCommand('increx', 'IncrementExistingKey');
|
||||
|
||||
$client->set('foo', 10);
|
||||
|
||||
var_dump($client->increx('foo')); // int(11)
|
||||
var_dump($client->increx('bar')); // NULL
|
||||
@@ -1,19 +1,9 @@
|
||||
<?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__.'/../autoload.php';
|
||||
require_once '../lib/Predis.php';
|
||||
|
||||
$single_server = array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'database' => 15
|
||||
);
|
||||
|
||||
@@ -31,3 +21,4 @@ $multiple_servers = array(
|
||||
'alias' => 'second',
|
||||
),
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
|
||||
use Predis\ConnectionParameters;
|
||||
use Predis\Commands\ICommand;
|
||||
use Predis\Network\StreamConnection;
|
||||
|
||||
class SimpleDebuggableConnection extends StreamConnection
|
||||
{
|
||||
private $tstart = 0;
|
||||
private $debugBuffer = array();
|
||||
|
||||
public function connect()
|
||||
{
|
||||
$this->tstart = microtime(true);
|
||||
|
||||
parent::connect();
|
||||
}
|
||||
|
||||
private function storeDebug(ICommand $command, $direction)
|
||||
{
|
||||
$firtsArg = $command->getArgument(0);
|
||||
$timestamp = round(microtime(true) - $this->tstart, 4);
|
||||
|
||||
$debug = $command->getId();
|
||||
$debug .= isset($firtsArg) ? " $firtsArg " : ' ';
|
||||
$debug .= "$direction $this";
|
||||
$debug .= " [{$timestamp}s]";
|
||||
|
||||
$this->debugBuffer[] = $debug;
|
||||
}
|
||||
|
||||
public function writeCommand(ICommand $command)
|
||||
{
|
||||
parent::writeCommand($command);
|
||||
|
||||
$this->storeDebug($command, '->');
|
||||
}
|
||||
|
||||
public function readResponse(ICommand $command)
|
||||
{
|
||||
$reply = parent::readResponse($command);
|
||||
$this->storeDebug($command, '<-');
|
||||
|
||||
return $reply;
|
||||
}
|
||||
|
||||
public function getDebugBuffer()
|
||||
{
|
||||
return $this->debugBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'connections' => array(
|
||||
'tcp' => 'SimpleDebuggableConnection',
|
||||
),
|
||||
);
|
||||
|
||||
$client = new Predis\Client($single_server, $options);
|
||||
$client->set('foo', 'bar');
|
||||
$client->get('foo');
|
||||
$client->info();
|
||||
|
||||
print_r($client->getConnection()->getDebugBuffer());
|
||||
|
||||
/* OUTPUT:
|
||||
Array
|
||||
(
|
||||
[0] => SELECT 15 -> 127.0.0.1:6379 [0.0008s]
|
||||
[1] => SELECT 15 <- 127.0.0.1:6379 [0.0012s]
|
||||
[2] => SET foo -> 127.0.0.1:6379 [0.0014s]
|
||||
[3] => SET foo <- 127.0.0.1:6379 [0.0014s]
|
||||
[4] => GET foo -> 127.0.0.1:6379 [0.0016s]
|
||||
[5] => GET foo <- 127.0.0.1:6379 [0.0018s]
|
||||
[6] => INFO -> 127.0.0.1:6379 [0.002s]
|
||||
[7] => INFO <- 127.0.0.1:6379 [0.0025s]
|
||||
)
|
||||
*/
|
||||
@@ -1,25 +1,16 @@
|
||||
<?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 'SharedConfigurations.php';
|
||||
require_once 'SharedConfigurations.php';
|
||||
|
||||
// simple set and get scenario
|
||||
|
||||
$client = new Predis\Client($single_server);
|
||||
$redis = new Predis_Client($single_server);
|
||||
|
||||
$client->set('library', 'predis');
|
||||
$retval = $client->get('library');
|
||||
$redis->set('library', 'predis');
|
||||
$retval = $redis->get('library');
|
||||
|
||||
var_dump($retval);
|
||||
print_r($retval);
|
||||
|
||||
/* OUTPUT
|
||||
string(6) "predis"
|
||||
predis
|
||||
*/
|
||||
?>
|
||||
|
||||
+3052
File diff suppressed because it is too large
Load Diff
@@ -1,57 +0,0 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Implements a lightweight PSR-0 compliant autoloader.
|
||||
*
|
||||
* @author Eric Naeseth <eric@thumbtack.com>
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
private $baseDir;
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* @param string $baseDirectory Base directory where the source files are located.
|
||||
*/
|
||||
public function __construct($baseDirectory = null)
|
||||
{
|
||||
$this->baseDir = $baseDirectory ?: dirname(__FILE__);
|
||||
$this->prefix = __NAMESPACE__ . '\\';
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the autoloader class with the PHP SPL autoloader.
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
spl_autoload_register(array(new self, 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a class from a file using its fully qualified name.
|
||||
*
|
||||
* @param string $className Fully qualified name of a class.
|
||||
*/
|
||||
public function autoload($className)
|
||||
{
|
||||
if (0 !== strpos($className, $this->prefix)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$relativeClassName = substr($className, strlen($this->prefix));
|
||||
$classNameParts = explode('\\', $relativeClassName);
|
||||
|
||||
require_once $this->baseDir.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $classNameParts).'.php';
|
||||
}
|
||||
}
|
||||
@@ -1,399 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use Predis\Commands\ICommand;
|
||||
use Predis\Options\IClientOptions;
|
||||
use Predis\Network\IConnection;
|
||||
use Predis\Network\IConnectionSingle;
|
||||
use Predis\Profiles\IServerProfile;
|
||||
use Predis\Options\ClientOptions;
|
||||
use Predis\Profiles\ServerProfile;
|
||||
use Predis\PubSub\PubSubContext;
|
||||
use Predis\Pipeline\PipelineContext;
|
||||
use Predis\Transaction\MultiExecContext;
|
||||
|
||||
/**
|
||||
* Main class that exposes the most high-level interface to interact with Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
const VERSION = '0.7.1';
|
||||
|
||||
private $options;
|
||||
private $profile;
|
||||
private $connection;
|
||||
private $connections;
|
||||
|
||||
/**
|
||||
* Initializes a new client with optional connection parameters and client options.
|
||||
*
|
||||
* @param mixed $parameters Connection parameters for one or multiple servers.
|
||||
* @param mixed $options Options that specify certain behaviours for the client.
|
||||
*/
|
||||
public function __construct($parameters = null, $options = null)
|
||||
{
|
||||
$options = $this->filterOptions($options);
|
||||
$this->options = $options;
|
||||
$this->profile = $options->profile;
|
||||
$this->connections = $options->connections;
|
||||
$this->connection = $this->initializeConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of Predis\Options\ClientOptions from various types of
|
||||
* arguments (string, array, Predis\Profiles\ServerProfile) or returns the
|
||||
* passed object if it is an instance of Predis\Options\ClientOptions.
|
||||
*
|
||||
* @param mixed $options Client options.
|
||||
* @return ClientOptions
|
||||
*/
|
||||
protected function filterOptions($options)
|
||||
{
|
||||
if ($options === null) {
|
||||
return new ClientOptions();
|
||||
}
|
||||
if (is_array($options)) {
|
||||
return new ClientOptions($options);
|
||||
}
|
||||
if ($options instanceof IClientOptions) {
|
||||
return $options;
|
||||
}
|
||||
if ($options instanceof IServerProfile || is_string($options)) {
|
||||
return new ClientOptions(array('profile' => $options));
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Invalid type for client options");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes one or multiple connection (cluster) objects from various
|
||||
* types of arguments (string, array) or returns the passed object if it
|
||||
* implements the Predis\Network\IConnection interface.
|
||||
*
|
||||
* @param mixed $parameters Connection parameters or instance.
|
||||
* @return IConnection
|
||||
*/
|
||||
protected function initializeConnection($parameters)
|
||||
{
|
||||
if ($parameters instanceof IConnection) {
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
if (is_array($parameters) && isset($parameters[0])) {
|
||||
$replication = isset($this->options->replication) && $this->options->replication;
|
||||
|
||||
$connection = $this->options->{$replication ? 'replication' : 'cluster'};
|
||||
$initializer = $replication ? 'createReplication' : 'createCluster';
|
||||
|
||||
return $this->connections->$initializer($connection, $parameters, $this->profile);
|
||||
}
|
||||
|
||||
return $this->connections->create($parameters, $this->profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server profile used by the client.
|
||||
*
|
||||
* @return IServerProfile
|
||||
*/
|
||||
public function getProfile()
|
||||
{
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client options specified upon initialization.
|
||||
*
|
||||
* @return ClientOptions
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection factory object used by the client.
|
||||
*
|
||||
* @return IConnectionFactory
|
||||
*/
|
||||
public function getConnectionFactory()
|
||||
{
|
||||
return $this->connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a client for the specified connection when the
|
||||
* client is connected to a cluster. The new instance will use the same
|
||||
* options of the original client.
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
public function getClientFor($connectionAlias)
|
||||
{
|
||||
if (($connection = $this->getConnection($connectionAlias)) === null) {
|
||||
throw new \InvalidArgumentException("Invalid connection alias: '$connectionAlias'");
|
||||
}
|
||||
|
||||
return new Client($connection, $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the connection to the server.
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$this->connection->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the server.
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->connection->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the server.
|
||||
*
|
||||
* This method is an alias of disconnect().
|
||||
*/
|
||||
public function quit()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the underlying connection is connected to Redis.
|
||||
*
|
||||
* @return Boolean True means that the connection is open.
|
||||
* False means that the connection is closed.
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return $this->connection->isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying connection instance or, when connected to a cluster,
|
||||
* one of the connection instances identified by its alias.
|
||||
*
|
||||
* @param string $id The alias of a connection when connected to a cluster.
|
||||
* @return IConnection
|
||||
*/
|
||||
public function getConnection($id = null)
|
||||
{
|
||||
if (isset($id)) {
|
||||
if (!Helpers::isAggregated($this->connection)) {
|
||||
$message = 'Retrieving connections by alias is supported only with aggregated connections (cluster or replication)';
|
||||
throw new NotSupportedException($message);
|
||||
}
|
||||
return $this->connection->getConnectionById($id);
|
||||
}
|
||||
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dinamically invokes a Redis command with the specified arguments.
|
||||
*
|
||||
* @param string $method The name of a Redis command.
|
||||
* @param array $arguments The arguments for the command.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
$command = $this->profile->createCommand($method, $arguments);
|
||||
return $this->connection->executeCommand($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the specified Redis command.
|
||||
*
|
||||
* @param string $method The name of a Redis command.
|
||||
* @param array $arguments The arguments for the command.
|
||||
* @return ICommand
|
||||
*/
|
||||
public function createCommand($method, $arguments = array())
|
||||
{
|
||||
return $this->profile->createCommand($method, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the specified Redis command.
|
||||
*
|
||||
* @param ICommand $command A Redis command.
|
||||
* @return mixed
|
||||
*/
|
||||
public function executeCommand(ICommand $command)
|
||||
{
|
||||
return $this->connection->executeCommand($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the specified Redis command on all the nodes of a cluster.
|
||||
*
|
||||
* @param ICommand $command A Redis command.
|
||||
* @return array
|
||||
*/
|
||||
public function executeCommandOnShards(ICommand $command)
|
||||
{
|
||||
if (Helpers::isCluster($this->connection)) {
|
||||
$replies = array();
|
||||
|
||||
foreach ($this->connection as $connection) {
|
||||
$replies[] = $connection->executeCommand($command);
|
||||
}
|
||||
|
||||
return $replies;
|
||||
}
|
||||
|
||||
return array($this->connection->executeCommand($command));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified initializer method on $this with 0, 1 or 2 arguments.
|
||||
*
|
||||
* TODO: Invert $argv and $initializer.
|
||||
*
|
||||
* @param array $argv Arguments for the initializer.
|
||||
* @param string $initializer The initializer method.
|
||||
* @return mixed
|
||||
*/
|
||||
private function sharedInitializer($argv, $initializer)
|
||||
{
|
||||
switch (count($argv)) {
|
||||
case 0:
|
||||
return $this->$initializer();
|
||||
|
||||
case 1:
|
||||
list($arg0) = $argv;
|
||||
return is_array($arg0) ? $this->$initializer($arg0) : $this->$initializer(null, $arg0);
|
||||
|
||||
case 2:
|
||||
list($arg0, $arg1) = $argv;
|
||||
return $this->$initializer($arg0, $arg1);
|
||||
|
||||
default:
|
||||
return $this->$initializer($this, $argv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pipeline context and returns it, or returns the results of
|
||||
* a pipeline executed inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed $arg,... Options for the context, a callable object, or both.
|
||||
* @return PipelineContext|array
|
||||
*/
|
||||
public function pipeline(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initPipeline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Pipeline context initializer.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return PipelineContext|array
|
||||
*/
|
||||
protected function initPipeline(Array $options = null, $callable = null)
|
||||
{
|
||||
$pipeline = new PipelineContext($this, $options);
|
||||
return $this->pipelineExecute($pipeline, $callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a pipeline context when a callable object is passed.
|
||||
*
|
||||
* @param array $options Options of the context initialization.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return PipelineContext|array
|
||||
*/
|
||||
private function pipelineExecute(PipelineContext $pipeline, $callable)
|
||||
{
|
||||
return isset($callable) ? $pipeline->execute($callable) : $pipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new transaction context and returns it, or returns the results of
|
||||
* a transaction executed inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed $arg,... Options for the context, a callable object, or both.
|
||||
* @return MultiExecContext|array
|
||||
*/
|
||||
public function multiExec(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initMultiExec');
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaction context initializer.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return MultiExecContext|array
|
||||
*/
|
||||
protected function initMultiExec(Array $options = null, $callable = null)
|
||||
{
|
||||
$transaction = new MultiExecContext($this, $options ?: array());
|
||||
return isset($callable) ? $transaction->execute($callable) : $transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Publish / Subscribe context and returns it, or executes it
|
||||
* inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed $arg,... Options for the context, a callable object, or both.
|
||||
* @return MultiExecContext|array
|
||||
*/
|
||||
public function pubSub(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initPubSub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish / Subscribe context initializer.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return PubSubContext
|
||||
*/
|
||||
protected function initPubSub(Array $options = null, $callable = null)
|
||||
{
|
||||
$pubsub = new PubSubContext($this, $options);
|
||||
|
||||
if (!isset($callable)) {
|
||||
return $pubsub;
|
||||
}
|
||||
|
||||
foreach ($pubsub as $message) {
|
||||
if (call_user_func($callable, $pubsub, $message) === false) {
|
||||
$pubsub->closeContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new monitor context.
|
||||
*
|
||||
* @return MonitorContext
|
||||
*/
|
||||
public function monitor()
|
||||
{
|
||||
return new MonitorContext($this);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Exception class that identifies client-side errors.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ClientException extends PredisException
|
||||
{
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
use Predis\Distribution\INodeKeyGenerator;
|
||||
|
||||
/**
|
||||
* Base class for Redis commands.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class Command implements ICommand
|
||||
{
|
||||
private $hash;
|
||||
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);
|
||||
unset($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the arguments array without filtering.
|
||||
*
|
||||
* @param array $arguments List of arguments.
|
||||
*/
|
||||
public function setRawArguments(Array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
unset($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the argument from the arguments list at the specified index.
|
||||
*
|
||||
* @param array $arguments Position of the argument.
|
||||
*/
|
||||
public function getArgument($index = 0)
|
||||
{
|
||||
if (isset($this->arguments[$index]) === true) {
|
||||
return $this->arguments[$index];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the command can return an hash for client-side sharding.
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return isset($this->arguments[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified array of keys will generate the same hash.
|
||||
*
|
||||
* @param array $keys Array of keys.
|
||||
* @return Boolean
|
||||
*/
|
||||
protected function checkSameHashForKeys(Array $keys)
|
||||
{
|
||||
if (($count = count($keys)) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentKey = Helpers::extractKeyTag($keys[0]);
|
||||
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
$nextKey = Helpers::extractKeyTag($keys[$i]);
|
||||
if ($currentKey !== $nextKey) {
|
||||
return false;
|
||||
}
|
||||
$currentKey = $nextKey;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHash(INodeKeyGenerator $distributor)
|
||||
{
|
||||
if (isset($this->hash)) {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
if ($this->canBeHashed()) {
|
||||
$key = Helpers::extractKeyTag($this->arguments[0]);
|
||||
$this->hash = $distributor->generateKey($key);
|
||||
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to reduce a list of arguments to a string.
|
||||
*
|
||||
* @param string $accumulator Temporary string.
|
||||
* @param string $argument Current argument.
|
||||
* @return string
|
||||
*/
|
||||
protected function toStringArgumentReducer($accumulator, $argument)
|
||||
{
|
||||
if (strlen($argument) > 32) {
|
||||
$argument = substr($argument, 0, 32) . '[...]';
|
||||
}
|
||||
$accumulator .= " $argument";
|
||||
|
||||
return $accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a partial string representation of the command with its arguments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return array_reduce(
|
||||
$this->getArguments(),
|
||||
array($this, 'toStringArgumentReducer'),
|
||||
$this->getId()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/auth
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionAuth extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'AUTH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/echo
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionEcho extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'ECHO';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/ping
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionPing extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PING';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data === 'PONG' ? true : false;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/quit
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionQuit extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'QUIT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/select
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ConnectionSelect extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'SELECT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hdel
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashDelete extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HDEL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return Helpers::filterVariadicValues($arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hexists
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashExists extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HEXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hget
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGet extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HGET';
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Iterators\MultiBulkResponseTuple;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hgetall
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGetAll extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HGETALL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
if ($data instanceof \Iterator) {
|
||||
return new MultiBulkResponseTuple($data);
|
||||
}
|
||||
|
||||
$result = array();
|
||||
for ($i = 0; $i < count($data); $i++) {
|
||||
$result[$data[$i]] = $data[++$i];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hmget
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashGetMultiple extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HMGET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return Helpers::filterVariadicValues($arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hincrby
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashIncrementBy extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HINCRBY';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hincrbyfloat
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashIncrementByFloat extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HINCRBYFLOAT';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hkeys
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashKeys extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HKEYS';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hlen
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashLength extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HLEN';
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hset
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSet extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HSET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hmset
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSetMultiple extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HMSET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
$flattenedKVs = array($arguments[0]);
|
||||
$args = $arguments[1];
|
||||
|
||||
foreach ($args as $k => $v) {
|
||||
$flattenedKVs[] = $k;
|
||||
$flattenedKVs[] = $v;
|
||||
}
|
||||
|
||||
return $flattenedKVs;
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hsetnx
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashSetPreserve extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HSETNX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/hvals
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class HashValues extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HVALS';
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Distribution\INodeKeyGenerator;
|
||||
|
||||
/**
|
||||
* Defines an abstraction representing a Redis command.
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface ICommand
|
||||
{
|
||||
/**
|
||||
* Gets the ID of a Redis command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
/**
|
||||
* Returns an hash of the command using the provided algorithm against the
|
||||
* key (used to calculate the distribution of keys with client-side sharding).
|
||||
*
|
||||
* @param INodeKeyGenerator $distributor Distribution algorithm.
|
||||
* @return int
|
||||
*/
|
||||
public function getHash(INodeKeyGenerator $distributor);
|
||||
|
||||
/**
|
||||
* Sets the arguments of the command.
|
||||
*
|
||||
* @param array $arguments List of arguments.
|
||||
*/
|
||||
public function setArguments(Array $arguments);
|
||||
|
||||
/**
|
||||
* Gets the arguments of the command.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArguments();
|
||||
|
||||
/**
|
||||
* Parses a reply buffer and returns a PHP object.
|
||||
*
|
||||
* @param string $data Binary string containing the whole reply.
|
||||
* @return mixed
|
||||
*/
|
||||
public function parseResponse($data);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Distribution\INodeKeyGenerator;
|
||||
|
||||
/**
|
||||
* Defines a command whose keys can be prefixed.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface IPrefixable
|
||||
{
|
||||
/**
|
||||
* Prefixes all the keys found in the arguments of the command.
|
||||
*
|
||||
* @param string $prefix String used to prefix the keys.
|
||||
*/
|
||||
public function prefixKeys($prefix);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/del
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyDelete extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'DEL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return Helpers::filterArrayArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
$args = $this->getArguments();
|
||||
if (count($args) === 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->checkSameHashForKeys($args);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/exists
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExists extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/expire
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExpire extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EXPIRE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/expireat
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyExpireAt extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EXPIREAT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/keys
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyKeys extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'KEYS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/keys
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
* @deprecated
|
||||
*/
|
||||
class KeyKeysV12x extends KeyKeys
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return explode(' ', $data);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/move
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyMove extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'MOVE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/persist
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPersist extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PERSIST';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pexpire
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPreciseExpire extends KeyExpire
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PEXPIRE';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pexpireat
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPreciseExpireAt extends KeyExpireAt
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PEXPIREAT';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/pttl
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPreciseTimeToLive extends KeyTimeToLive
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PTTL';
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/randomkey
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRandom extends Command
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RANDOMKEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data !== '' ? $data : null;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/rename
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRename extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RENAME';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/renamenx
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyRenamePreserve extends KeyRename
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RENAMENX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/sort
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeySort extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'SORT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
if (count($arguments) === 1) {
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
$query = array($arguments[0]);
|
||||
$sortParams = array_change_key_case($arguments[1], CASE_UPPER);
|
||||
|
||||
if (isset($sortParams['BY'])) {
|
||||
$query[] = 'BY';
|
||||
$query[] = $sortParams['BY'];
|
||||
}
|
||||
|
||||
if (isset($sortParams['GET'])) {
|
||||
$getargs = $sortParams['GET'];
|
||||
if (is_array($getargs)) {
|
||||
foreach ($getargs as $getarg) {
|
||||
$query[] = 'GET';
|
||||
$query[] = $getarg;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$query[] = 'GET';
|
||||
$query[] = $getargs;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($sortParams['LIMIT']) && is_array($sortParams['LIMIT'])
|
||||
&& count($sortParams['LIMIT']) == 2) {
|
||||
|
||||
$query[] = 'LIMIT';
|
||||
$query[] = $sortParams['LIMIT'][0];
|
||||
$query[] = $sortParams['LIMIT'][1];
|
||||
}
|
||||
|
||||
if (isset($sortParams['SORT'])) {
|
||||
$query[] = strtoupper($sortParams['SORT']);
|
||||
}
|
||||
|
||||
if (isset($sortParams['ALPHA']) && $sortParams['ALPHA'] == true) {
|
||||
$query[] = 'ALPHA';
|
||||
}
|
||||
|
||||
if (isset($sortParams['STORE'])) {
|
||||
$query[] = 'STORE';
|
||||
$query[] = $sortParams['STORE'];
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$arguments = $this->getArguments();
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
|
||||
if (($count = count($arguments)) > 1) {
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
switch ($arguments[$i]) {
|
||||
case 'BY':
|
||||
case 'STORE':
|
||||
$arguments[$i] = "$prefix{$arguments[++$i]}";
|
||||
break;
|
||||
|
||||
case 'GET':
|
||||
$value = $arguments[++$i];
|
||||
if ($value !== '#') {
|
||||
$arguments[$i] = "$prefix$value";
|
||||
}
|
||||
break;
|
||||
|
||||
case 'LIMIT';
|
||||
$i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/ttl
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyTimeToLive extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'TTL';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/type
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyType extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'TYPE';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lindex
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListIndex extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LINDEX';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/linsert
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListInsert extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LINSERT';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/llen
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListLength extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LLEN';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lpop
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopFirst extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LPOP';
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/blpop
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopFirstBlocking extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BLPOP';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[0])) {
|
||||
list($arguments, $timeout) = $arguments;
|
||||
array_push($arguments, $timeout);
|
||||
}
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::skipLast($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return $this->checkSameHashForKeys(
|
||||
array_slice(($args = $this->getArguments()), 0, count($args) - 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/rpop
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopLast extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPOP';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/brpop
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopLastBlocking extends ListPopFirstBlocking
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BRPOP';
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/rpoplpush
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopLastPushHead extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPOPLPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return $this->checkSameHashForKeys($this->getArguments());
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/brpoplpush
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPopLastPushHeadBlocking extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BRPOPLPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::skipLast($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return $this->checkSameHashForKeys(
|
||||
array_slice($args = $this->getArguments(), 0, count($args) - 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lpush
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPushHead extends ListPushTail
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LPUSH';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lpushx
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPushHeadX extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LPUSHX';
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/rpush
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPushTail extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return Helpers::filterVariadicValues($arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/rpushx
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListPushTailX extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPUSHX';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lrange
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListRange extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LRANGE';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lrem
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListRemove extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LREM';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/lset
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListSet extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LSET';
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/ltrim
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ListTrim extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LTRIM';
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* Class that defines a few helpers method for prefixing keys.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class PrefixHelpers
|
||||
{
|
||||
/**
|
||||
* Applies the specified prefix only the first argument.
|
||||
*
|
||||
* @param ICommand $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function first(ICommand $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments.
|
||||
*
|
||||
* @param ICommand $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function all(ICommand $command, $prefix)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
foreach ($arguments as &$key) {
|
||||
$key = "$prefix$key";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix only to even arguments in the list.
|
||||
*
|
||||
* @param ICommand $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function interleaved(ICommand $command, $prefix)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$length = count($arguments);
|
||||
|
||||
for ($i = 0; $i < $length; $i += 2) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments but the last one.
|
||||
*
|
||||
* @param ICommand $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function skipLast(ICommand $command, $prefix)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$length = count($arguments);
|
||||
|
||||
for ($i = 0; $i < $length - 1; $i++) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* Base class for Redis commands with prefixable keys.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class PrefixableCommand extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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\Commands\Processors;
|
||||
|
||||
use Predis\Commands\ICommand;
|
||||
|
||||
/**
|
||||
* A command processor processes commands before they are sent to Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface ICommandProcessor
|
||||
{
|
||||
/**
|
||||
* Processes a Redis command.
|
||||
*
|
||||
* @param ICommand $command Redis command.
|
||||
*/
|
||||
public function process(ICommand $command);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?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\Commands\Processors;
|
||||
|
||||
/**
|
||||
* A command processor chain processes a command using multiple chained command
|
||||
* processor before it is sent to Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface ICommandProcessorChain extends ICommandProcessor, \IteratorAggregate, \Countable
|
||||
{
|
||||
/**
|
||||
* Adds a command processor.
|
||||
*
|
||||
* @param ICommandProcessor $processor A command processor.
|
||||
*/
|
||||
public function add(ICommandProcessor $processor);
|
||||
|
||||
/**
|
||||
* Removes a command processor from the chain.
|
||||
*
|
||||
* @param ICommandProcessor $processor A command processor.
|
||||
*/
|
||||
public function remove(ICommandProcessor $processor);
|
||||
|
||||
/**
|
||||
* Returns an ordered list of the command processors in the chain.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProcessors();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?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\Commands\Processors;
|
||||
|
||||
/**
|
||||
* Defines an object that can process commands using command processors.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface IProcessingSupport
|
||||
{
|
||||
/**
|
||||
* Associates a command processor.
|
||||
*
|
||||
* @param ICommandProcessor $processor The command processor.
|
||||
*/
|
||||
public function setProcessor(ICommandProcessor $processor);
|
||||
|
||||
/**
|
||||
* Returns the associated command processor.
|
||||
*
|
||||
* @return ICommandProcessor
|
||||
*/
|
||||
public function getProcessor();
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?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\Commands\Processors;
|
||||
|
||||
use Predis\Commands\ICommand;
|
||||
use Predis\Commands\IPrefixable;
|
||||
|
||||
/**
|
||||
* Command processor that is used to prefix the keys contained in the arguments
|
||||
* of a Redis command.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPrefixProcessor implements ICommandProcessor
|
||||
{
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* @param string $prefix Prefix for the keys.
|
||||
*/
|
||||
public function __construct($prefix)
|
||||
{
|
||||
$this->setPrefix($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a prefix that is applied to all the keys.
|
||||
*
|
||||
* @param string $prefix Prefix for the keys.
|
||||
*/
|
||||
public function setPrefix($prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPrefix()
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ICommand $command)
|
||||
{
|
||||
if ($command instanceof IPrefixable) {
|
||||
$command->prefixKeys($this->prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
<?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\Commands\Processors;
|
||||
|
||||
use Predis\Commands\ICommand;
|
||||
|
||||
/**
|
||||
* Default implementation of a command processors chain.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ProcessorChain implements ICommandProcessorChain, \ArrayAccess
|
||||
{
|
||||
private $processors = array();
|
||||
|
||||
/**
|
||||
* @param array $processors List of instances of ICommandProcessor.
|
||||
*/
|
||||
public function __construct($processors = array())
|
||||
{
|
||||
foreach ($processors as $processor) {
|
||||
$this->add($processor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(ICommandProcessor $processor)
|
||||
{
|
||||
$this->processors[] = $processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove(ICommandProcessor $processor)
|
||||
{
|
||||
$index = array_search($processor, $this->processors, true);
|
||||
if ($index !== false) {
|
||||
unset($this[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ICommand $command)
|
||||
{
|
||||
$count = count($this->processors);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$this->processors[$i]->process($command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProcessors()
|
||||
{
|
||||
return $this->processors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the list of command processor in the chain.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of command processors in the chain.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetExists($index)
|
||||
{
|
||||
return isset($this->processors[$index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetGet($index)
|
||||
{
|
||||
return $this->processors[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetSet($index, $processor)
|
||||
{
|
||||
if (!$processor instanceof ICommandProcessor) {
|
||||
throw new \InvalidArgumentException(
|
||||
'A processor chain can hold only instances of classes implementing '.
|
||||
'the Predis\Commands\Preprocessors\ICommandProcessor interface'
|
||||
);
|
||||
}
|
||||
|
||||
$this->processors[$index] = $processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetUnset($index)
|
||||
{
|
||||
unset($this->processors[$index]);
|
||||
$this->processors = array_values($this->processors);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/publish
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class PubSubPublish extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PUBLISH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/subscribe
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class PubSubSubscribe extends Command implements IPrefixable
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'SUBSCRIBE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return Helpers::filterArrayArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function canBeHashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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\Commands;
|
||||
|
||||
use Predis\Helpers;
|
||||
|
||||
/**
|
||||
* @link http://redis.io/commands/psubscribe
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class PubSubSubscribeByPattern extends PubSubSubscribe
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PSUBSCRIBE';
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user