A flexible and feature-complete Redis client for PHP.

Overview

Predis

Software license Latest stable Latest development Monthly installs Build status

A flexible and feature-complete Redis client for PHP 7.2 and newer.

ATTENTION: you are on the README file of an unstable branch of Predis specifically meant for the development of future releases. This means that the code on this branch is potentially unstable, and breaking change may happen without any prior notice. Do not use it in production environments or use it at your own risk!

Predis does not require any additional C extension by default, but it can be optionally paired with phpiredis to lower the overhead of the serialization and parsing of the Redis RESP Protocol.

More details about this project can be found on the frequently asked questions.

Main features

  • Support for Redis from 2.0 to 6.0.
  • Support for clustering using client-side sharding and pluggable keyspace distributors.
  • Support for redis-cluster (Redis >= 3.0).
  • Support for master-slave replication setups and redis-sentinel.
  • Transparent key prefixing of keys using a customizable prefix strategy.
  • Command pipelining on both single nodes and clusters (client-side sharding only).
  • Abstraction for Redis transactions (Redis >= 2.0) and CAS operations (Redis >= 2.2).
  • Abstraction for Lua scripting (Redis >= 2.6) and automatic switching between EVALSHA or EVAL.
  • Abstraction for SCAN, SSCAN, ZSCAN and HSCAN (Redis >= 2.8) based on PHP iterators.
  • Connections are established lazily by the client upon the first command and can be persisted.
  • Connections can be established via TCP/IP (also TLS/SSL-encrypted) or UNIX domain sockets.
  • Support for Webdis (requires both ext-curl and ext-phpiredis).
  • Support for custom connection classes for providing different network or protocol backends.
  • Flexible system for defining custom commands and override the default ones.

How to install and use Predis

This library can be found on Packagist for an easier management of projects dependencies using Composer. Compressed archives of each release are available on GitHub.

Loading the library

Predis relies on the autoloading features of PHP to load its files when needed and complies with the PSR-4 standard. Autoloading is handled automatically when dependencies are managed through Composer, but it is also possible to leverage its own autoloader in projects or scripts lacking any autoload facility:

// Prepend a base path if Predis is not available in your "include_path".
require 'Predis/Autoloader.php';

Predis\Autoloader::register();

Connecting to Redis

When creating a client instance without passing any connection parameter, Predis assumes 127.0.0.1 and 6379 as default host and port. The default timeout for the connect() operation is 5 seconds:

$client = new Predis\Client();
$client->set('foo', 'bar');
$value = $client->get('foo');

Connection parameters can be supplied either in the form of URI strings or named arrays. The latter is the preferred way to supply parameters, but URI strings can be useful when parameters are read from non-structured or partially-structured sources:

// Parameters passed using a named array:
$client = new Predis\Client([
    'scheme' => 'tcp',
    'host'   => '10.0.0.1',
    'port'   => 6379,
]);

// Same set of parameters, passed using an URI string:
$client = new Predis\Client('tcp://10.0.0.1:6379');

Password protected servers can be accessed by adding password to the parameters set. When ACLs are enabled on Redis >= 6.0, both username and password are required for user authentication.

It is also possible to connect to local instances of Redis using UNIX domain sockets, in this case the parameters must use the unix scheme and specify a path for the socket file:

$client = new Predis\Client(['scheme' => 'unix', 'path' => '/path/to/redis.sock']);
$client = new Predis\Client('unix:/path/to/redis.sock');

The client can leverage TLS/SSL encryption to connect to secured remote Redis instances without the need to configure an SSL proxy like stunnel. This can be useful when connecting to nodes running on various cloud hosting providers. Encryption can be enabled with using the tls scheme and an array of suitable options passed via the ssl parameter:

// Named array of connection parameters:
$client = new Predis\Client([
  'scheme' => 'tls',
  'ssl'    => ['cafile' => 'private.pem', 'verify_peer' => true],
]);

// Same set of parameters, but using an URI string:
$client = new Predis\Client('tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1');

The connection schemes redis (alias of tcp) and rediss (alias of tls) are also supported, with the difference that URI strings containing these schemes are parsed following the rules described on their respective IANA provisional registration documents.

The actual list of supported connection parameters can vary depending on each connection backend so it is recommended to refer to their specific documentation or implementation for details.

Predis can aggregate multiple connections when providing an array of connection parameters and the appropriate option to instruct the client about how to aggregate them (clustering, replication or a custom aggregation logic). Named arrays and URI strings can be mixed when providing configurations for each node:

$client = new Predis\Client([
    'tcp://10.0.0.1?alias=first-node', ['host' => '10.0.0.2', 'alias' => 'second-node'],
], [
    'cluster' => 'predis',
]);

See the aggregate connections section of this document for more details.

Connections to Redis are lazy meaning that the client connects to a server only if and when needed. While it is recommended to let the client do its own stuff under the hood, there may be times when it is still desired to have control of when the connection is opened or closed: this can easily be achieved by invoking $client->connect() and $client->disconnect(). Please note that the effect of these methods on aggregate connections may differ depending on each specific implementation.

Client configuration

Many aspects and behaviors of the client can be configured by passing specific client options to the second argument of Predis\Client::__construct():

$client = new Predis\Client($parameters, ['prefix' => 'sample:']);

Options are managed using a mini DI-alike container and their values can be lazily initialized only when needed. The client options supported by default in Predis are:

  • prefix: prefix string applied to every key found in commands.
  • exceptions: whether the client should throw or return responses upon Redis errors.
  • connections: list of connection backends or a connection factory instance.
  • cluster: specifies a cluster backend (predis, redis or callable).
  • replication: specifies a replication backend (predis, sentinel or callable).
  • aggregate: configures the client with a custom aggregate connection (callable).
  • parameters: list of default connection parameters for aggregate connections.
  • commands: specifies a command factory instance to use through the library.

Users can also provide custom options with values or callable objects (for lazy initialization) that are stored in the options container for later use through the library.

Aggregate connections

Aggregate connections are the foundation upon which Predis implements clustering and replication and they are used to group multiple connections to single Redis nodes and hide the specific logic needed to handle them properly depending on the context. Aggregate connections usually require an array of connection parameters along with the appropriate client option when creating a new client instance.

Cluster

Predis can be configured to work in clustering mode with a traditional client-side sharding approach to create a cluster of independent nodes and distribute the keyspace among them. This approach needs some sort of external health monitoring of nodes and requires the keyspace to be rebalanced manually when nodes are added or removed:

$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options    = ['cluster' => 'predis'];

$client = new Predis\Client($parameters);

Along with Redis 3.0, a new supervised and coordinated type of clustering was introduced in the form of redis-cluster. This kind of approach uses a different algorithm to distribute the keyspaces, with Redis nodes coordinating themselves by communicating via a gossip protocol to handle health status, rebalancing, nodes discovery and request redirection. In order to connect to a cluster managed by redis-cluster, the client requires a list of its nodes (not necessarily complete since it will automatically discover new nodes if necessary) and the cluster client options set to redis:

$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options    = ['cluster' => 'redis'];

$client = new Predis\Client($parameters, $options);

Replication

The client can be configured to operate in a single master / multiple slaves setup to provide better service availability. When using replication, Predis recognizes read-only commands and sends them to a random slave in order to provide some sort of load-balancing and switches to the master as soon as it detects a command that performs any kind of operation that would end up modifying the keyspace or the value of a key. Instead of raising a connection error when a slave fails, the client attempts to fall back to a different slave among the ones provided in the configuration.

The basic configuration needed to use the client in replication mode requires one Redis server to be identified as the master (this can be done via connection parameters by setting the role parameter to master) and one or more slaves (in this case setting role to slave for slaves is optional):

$parameters = ['tcp://10.0.0.1?role=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options    = ['replication' => 'predis'];

$client = new Predis\Client($parameters, $options);

The above configuration has a static list of servers and relies entirely on the client's logic, but it is possible to rely on redis-sentinel for a more robust HA environment with sentinel servers acting as a source of authority for clients for service discovery. The minimum configuration required by the client to work with redis-sentinel is a list of connection parameters pointing to a bunch of sentinel instances, the replication option set to sentinel and the service option set to the name of the service:

$sentinels = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options   = ['replication' => 'sentinel', 'service' => 'mymaster'];

$client = new Predis\Client($sentinels, $options);

If the master and slave nodes are configured to require an authentication from clients, a password must be provided via the global parameters client option. This option can also be used to specify a different database index. The client options array would then look like this:

$options = [
    'replication' => 'sentinel',
    'service' => 'mymaster',
    'parameters' => [
        'password' => $secretpassword,
        'database' => 10,
    ],
];

While Predis is able to distinguish commands performing write and read-only operations, EVAL and EVALSHA represent a corner case in which the client switches to the master node because it cannot tell when a Lua script is safe to be executed on slaves. While this is indeed the default behavior, when certain Lua scripts do not perform write operations it is possible to provide an hint to tell the client to stick with slaves for their execution:

$parameters = ['tcp://10.0.0.1?role=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options    = ['replication' => function () {
    // Set scripts that won't trigger a switch from a slave to the master node.
    $strategy = new Predis\Replication\ReplicationStrategy();
    $strategy->setScriptReadOnly($LUA_SCRIPT);

    return new Predis\Connection\Replication\MasterSlaveReplication($strategy);
}];

$client = new Predis\Client($parameters, $options);
$client->eval($LUA_SCRIPT, 0);             // Sticks to slave using `eval`...
$client->evalsha(sha1($LUA_SCRIPT), 0);    // ... and `evalsha`, too.

The examples directory contains a few scripts that demonstrate how the client can be configured and used to leverage replication in both basic and complex scenarios.

Command pipelines

Pipelining can help with performances when many commands need to be sent to a server by reducing the latency introduced by network round-trip timings. Pipelining also works with aggregate connections. The client can execute the pipeline inside a callable block or return a pipeline instance with the ability to chain commands thanks to its fluent interface:

// Executes a pipeline inside the given callable block:
$responses = $client->pipeline(function ($pipe) {
    for ($i = 0; $i < 1000; $i++) {
        $pipe->set("key:$i", str_pad($i, 4, '0', 0));
        $pipe->get("key:$i");
    }
});

// Returns a pipeline that can be chained thanks to its fluent interface:
$responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute();

Transactions

The client provides an abstraction for Redis transactions based on MULTI and EXEC with a similar interface to command pipelines:

// Executes a transaction inside the given callable block:
$responses = $client->transaction(function ($tx) {
    $tx->set('foo', 'bar');
    $tx->get('foo');
});

// Returns a transaction that can be chained thanks to its fluent interface:
$responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute();

This abstraction can perform check-and-set operations thanks to WATCH and UNWATCH and provides automatic retries of transactions aborted by Redis when WATCHed keys are touched. For an example of a transaction using CAS you can see the following example.

Adding new commands

While we try to update Predis to stay up to date with all the commands available in Redis, you might prefer to stick with an old version of the library or provide a different way to filter arguments or parse responses for specific commands. To achieve that, Predis provides the ability to implement new command classes to define or override commands in the default command factory used by the client:

// Define a new command by extending Predis\Command\Command:
class BrandNewRedisCommand extends Predis\Command\Command
{
    public function getId()
    {
        return 'NEWCMD';
    }
}

// Inject your command in the current command factory:
$client = new Predis\Client($parameters, [
    'commands' => [
        'newcmd' => 'BrandNewRedisCommand',
    ],
]);

$response = $client->newcmd();

There is also a method to send raw commands without filtering their arguments or parsing responses. Users must provide the list of arguments for the command as an array, following the signatures as defined by the Redis documentation for commands:

$response = $client->executeRaw(['SET', 'foo', 'bar']);

Script commands

While it is possible to leverage Lua scripting on Redis 2.6+ using directly EVAL and EVALSHA, Predis offers script commands as an higher level abstraction built upon them to make things simple. Script commands can be registered in the command factory used by the client and are accessible as if they were plain Redis commands, but they define Lua scripts that get transmitted to the server for remote execution. Internally they use EVALSHA by default and identify a script by its SHA1 hash to save bandwidth, but EVAL is used as a fall back when needed:

// Define a new script command by extending Predis\Command\ScriptCommand:
class ListPushRandomValue extends Predis\Command\ScriptCommand
{
    public function getKeysCount()
    {
        return 1;
    }

    public function getScript()
    {
        return <<<LUA
math.randomseed(ARGV[1])
local rnd = tostring(math.random())
redis.call('lpush', KEYS[1], rnd)
return rnd
LUA;
    }
}

// Inject the script command in the current command factory:
$client = new Predis\Client($parameters, [
    'commands' => [
        'lpushrand' => 'ListPushRandomValue',
    ],
]);

$response = $client->lpushrand('random_values', $seed = mt_rand());

Customizable connection backends

Predis can use different connection backends to connect to Redis. Two of them leverage a third party extension such as phpiredis resulting in major performance gains especially when dealing with big multibulk responses. While one is based on PHP streams, the other is based on socket resources provided by ext-socket. Both support TCP/IP and UNIX domain sockets:

$client = new Predis\Client('tcp://127.0.0.1', [
    'connections' => [
        'tcp'  => 'Predis\Connection\PhpiredisStreamConnection',  // PHP stream resources
        'unix' => 'Predis\Connection\PhpiredisSocketConnection',  // ext-socket resources
    ],
]);

The client can also be configured to rely on a phpiredis-backend by specifying a descriptive string for the connections client option. Supported string values are:

  • phpiredis-stream maps tcp, redis and unix to Predis\Connection\PhpiredisStreamConnection
  • phpiredis-socket maps tcp, redis and unix to Predis\Connection\PhpiredisSocketConnection
  • phpiredis is simply an alias of phpiredis-stream
$client = new Predis\Client('tcp://127.0.0.1', ['connections' => 'phpiredis']);

Developers can create their own connection classes to support whole new network backends, extend existing classes or provide completely different implementations. Connection classes must implement Predis\Connection\NodeConnectionInterface or extend Predis\Connection\AbstractConnection:

class MyConnectionClass implements Predis\Connection\NodeConnectionInterface
{
    // Implementation goes here...
}

// Use MyConnectionClass to handle connections for the `tcp` scheme:
$client = new Predis\Client('tcp://127.0.0.1', [
    'connections' => ['tcp' => 'MyConnectionClass'],
]);

For a more in-depth insight on how to create new connection backends you can refer to the actual implementation of the standard connection classes available in the Predis\Connection namespace.

Development

Reporting bugs and contributing code

Contributions to Predis are highly appreciated either in the form of pull requests for new features, bug fixes, or just bug reports. We only ask you to adhere to a basic set of rules before submitting your changes or filing bugs on the issue tracker to make it easier for everyone to stay consistent while working on the project.

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 and that can optionally perform integration tests against a running instance of Redis (required >= 2.4.0 in order to verify the correct behavior of the implementation of each command. Integration tests for unsupported Redis commands are automatically skipped. If you do not have Redis up and running, integration tests can be disabled. See the tests README for more details about testing this library.

Predis uses GitHub Actions for continuous integration and the history for past and current builds can be found on its actions page.

Other

Project related links

Author

License

The code for Predis is distributed under the terms of the MIT license (see LICENSE).

Comments
  • Support for Redis Sentinel

    Support for Redis Sentinel

    I would be happy to contribute to predis development by implementing automatic master/slave resolution and connection based on the configured sentinels. I tried to explore the Predis codebase, but unfortunately could not figure out where to start.

    In practice, we should be able to enter the sentinel addresses instead direct master/slave ip addresses and provide the name of the master. For example:

    $sentinels = array(
        'tcp://10.0.0.1:26379/',
        'tcp://10.0.0.2:26379/'
    );
    $redis = new Predis\Client($sentinels, array('sentinel_master' => 'mymaster');
    

    One of the configured sentinels should be connected and sent queries to get the master ip: SENTINEL get-master-addr-by-name mymaster, slaves SENTINEL slaves mymaster and finally create the actual aggregated connection based on the received information.

    Should I create a completely new connection type, extend an existing class or modify something? I also expect that I should implement two new command classes for the two sentinel commands.

    Some references:

    • http://redis.io/topics/sentinel
    • http://redis.io/topics/sentinel-clients
    feature redis-sentinel needs feedback 
    opened by vmattila 70
  • @method tags on \Predis\Client

    @method tags on \Predis\Client

    Dear @nrk,

    Would you be opposed to having @method tags on the \Predis\Client class? This could help IDEs apply auto-completion and for the redis expressions and to prevent IDEs from showing errors with regards to 'missing methods'.

    documentation 
    opened by mvriel 33
  • [2.0] Drop support for PHP 5.3

    [2.0] Drop support for PHP 5.3

    Now that (as of writing) the release of v1.1.0 is just matter of a few days and that with this new version Predis basically supports everything needed, I'm starting to play with some changes and ideas for v2.0 that would really benefit from bumping the major required version of PHP thus dropping support for PHP 5.3. My plan is to switch to PHP 5.5 as the minimum required version of PHP which is already the same requirement of big and widespread fameworks such as Symfony (3.0) and Laravel (5.1), making it a sane choice I think. This would help removing some annoying stuff from the code base here simply because of PHP 5.3 and actually improve other parts (e.g. having traits would be great with command classes).

    In the end I'm strongly biased toward going forward and forget about PHP 5.3 but I'd really love to hear what developers using Predis think about such a major decision. Keep in mind that with 2.0 I also plan to introduce some major breaking changes in the API anyway (aside from what concerns Redis commands as they will still take the same arguments and return the same values) but at the same time there are no plans for any new major feature related to Redis (there's nothing new in this respect) so I guess this is the ideal moment for such a change, and v1.x will still serve well for those that really need to stay on PHP 5.3 or 5.4 especially considered that I plan to maintain Predis v1.x for a while for bug fixes and eventual new minor features.

    Your thoughs?

    needs feedback 
    opened by nrk 32
  • Fix PhpUnit 8 tests

    Fix PhpUnit 8 tests

    This PR tries to fix the test suite for Predis on PHPUnit 8. All of the tests are running perfectly, except this test in:

    • Predis\Connection\Aggregate\SentinelReplicationTest::testMethodQuerySentinelFetchesMasterNodeSlaveNodesAndSentinelNodes Screenshot from 2020-08-16 02-15-44

    I need help to fix the failing test :smiley:.

    tests 
    opened by srmklive 29
  • Error while reading line from the server

    Error while reading line from the server

    CommunicationExceptions are thrown with the message 'Error while reading line from the server' from time to time. The Predis part of an example stack trace:

    Message: Error while reading line from the server
    Thrown at: /var/www/lib/redis/Predis.php:1568
    Trace:
    #0 /var/www/lib/redis/Predis.php(1636): Predis\Connection->onCommunicationException('Error while rea...')
    #1 /var/www/lib/redis/Predis.php(724): Predis\Connection->readLine()
    #2 /var/www/lib/redis/Predis.php(1577): Predis\FastResponseReader->read(Object(Predis\Connection))
    #3 /var/www/lib/redis/Predis.php(1586): Predis\Connection->readResponse(Object(Predis\Commands\Auth))
    #4 /var/www/lib/redis/Predis.php(225): Predis\Connection->executeCommand(Object(Predis\Commands\Auth))
    #5 /var/www/lib/redis/RedisProxy.php(21): Predis\Client->__call('auth', Array)
    #6 /var/www/lib/redis/RedisProxy.php(21): Predis\Client->auth('password')
    

    We couldn't find anything in common in the affected scripts. Some errors are from a local Redis server, some from a remote one. An example that sometimes generates this error:

    The script is run by Apache, browsers call it directly by URL, so there can be a lot of instances running at once. The following Redis commands are run via Predis (in this order; a, b , c and d are different tables):

    • AUTH
    • SELECT a
    • EXISTS
    • (if a condition is met) SETEX
    • SELECT b
    • RPUSH
    • if a condition is met
      • SELECT b
      • INCR
      • SELECT c
      • GET
      • SELECT d
      • RPUSH

    The bold commands are those that have ever generated the error. The majority (99%) is on AUTH.

    Environment:

    $ redis-server -v
    Redis server version 2.2.4 (00000000:0)
    
    Predis version 0.6.6
    
    $ php -v
    PHP 5.3.3-0.dotdeb.1 with Suhosin-Patch (cli) (built: Oct  1 2010 08:49:29) 
    Copyright (c) 1997-2009 The PHP Group
    Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
        with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans
    
    $ /usr/sbin/apache2ctl -v
    Server version: Apache/2.2.9 (Debian)
    Server built:   Apr 20 2010 15:40:17
    
    
    documentation 
    opened by abesto 28
  • Roadmap to v2.0

    Roadmap to v2.0

    Some thoughts on the future roadmap.

    v1.1

    • Bug fixes only
    • Maintain support for PHP 5.6 - 7.4 and Redis 3-5

    PHP 7.2 is EOL will get security patches only until 30 Nov 2020.

    v2.0

    • Drop HHVM & PEAR
    • Support PHP 7.2 - 8.0
    • Merge new features and new Redis commands
    • Support for Redis 3-6?
    • API documentation?
    • Move to GH Actions?
    help wanted 
    opened by tillkruss 23
  • Error while reading line from the server

    Error while reading line from the server

    Using redis for php 5.2 branch. I'm getting random "Error while reading line from the server" error. The command i used is lpush a serialized string.

    I'm using predis on a php daemon script, meaning it's up all the time. I've already set the timeout for redis.conf to 0.

    opened by googleguy 23
  • Using local patches for dev dependencies breaks projects that use cweagans/composer-patches

    Using local patches for dev dependencies breaks projects that use cweagans/composer-patches

    Describe the bug

    Follow-up of https://github.com/predis/predis/issues/632, which didn't fully address this issue

    Adding patches to composer.json for dev dependencies seems incorrect to me, for two reasons:

    a) The local patch files won't be found in the module, AFAIK composer-patches won't look there b) Even if they would be found, the project is likely to use a different version of phpunit where the patches don't apply.

    To Reproduce Steps to reproduce the behavior:

    1. composer init
    2. composer require cweagans/composer-patches predis/predis
    3. composer config extra.enable-patching true
    4. composer require --dev phpunit/phpunit
      - Applying patches for phpunit/phpunit
        ./tests/phpunit_php7.patch (Fix PHP 7 compatibility)
       Could not apply patch! Skipping. The error was: The "./tests/phpunit_php7.patch" file could not be downloaded: failed to open stream: No such file or directory
        ./tests/phpunit_php8.patch (Fix PHP 8 compatibility)
       Could not apply patch! Skipping. The error was: The "./tests/phpunit_php8.patch" file could not be downloaded: failed to open stream: No such file or directory
    

    Expected behavior A clear and concise description of what you expected to happen.

    Versions (please complete the following information):

    • Predis: 1.1.x
    • PHP 7.4
    • Redis Server irrelevant
    • OS: Ubuntu 20.10

    I don't think it is possible to do this, not without cweagans/composer-patches introducing a patches-dev. My suggestion would be to switch to applying those patches with a script/travis commands (or whatever CI you use)

    bug 
    opened by Berdir 21
  • Error while reading line from the server

    Error while reading line from the server

    We're seeing the following error quite a lot in our application and struggling to understand why

    Error while reading line from the server. [tcp://aws-domain:port] {"exception":"[object] (Predis\\Connection\\ConnectionException(code: 0): Error while reading line from the server. [tcp://aws-domain:port] at /app/vendor/predis/predis/src/Connection/AbstractConnection.php:155)"} [] 
    

    Do you have any tips on how to debug this sort of issue to see what the cause was? We have full stack traces in Sentry but there doesn't seem to be a pattern of when the error occurs.

    Things we've tried

    • Set the redis.default.read_write_timeout value to 0 in Laravel (/config/database.php)
    • Disabled php artisan horizon:snapshot, this almost always resulted in the error appearing

    Setup

    • Heroku Redis (Hobby dev)
    • laravel/laravel (5.5.40) d724ce0aa61bbd9adf658215eec484f5dd6711d6
    • laravel/horizon (v1.2.3) 36ef9e2d6e09e617cf801050326a69e876ff5535
    • predis (v1.1.1) f0210e38881631afeafb56ab43405a92cafd9fd1
    • PHP 7.2.5 (cli) (built: Apr 25 2018 03:07:35) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.5, Copyright (c) 1999-2018, by Zend Technologies
    opened by carltondickson 21
  • Unable to connect to TLS Elasticcache cluster without specifying all nodes in cluster

    Unable to connect to TLS Elasticcache cluster without specifying all nodes in cluster

    Hello,

    I am having issues using Predis to connect to an Elasticcache cluster, unless I specify all nodes in the cluster in this way:

    $cluster = [
    'tls://tls-cluster-node-001:6379',
    'tls://tls-cluster-node-002:6379',
    'tls://tls-cluster-node-003:6379'
    ];
    $client = new \Predis\Client($cluster, ['scheme' => 'tls', 'cluster' => 'redis']
    

    If I list the cluster configuration endpoint from AWS (using tls URI scheme) as the only endpoint, I get the following error:

    PHP Fatal error:  Uncaught exception 'Predis\ClientException' with message 'No connections available in the pool' in /opt/php/php-5.6.8/share/pear/Predis/Connection/Aggregate/RedisCluster.php:337
    

    Additionally, if I only list one node in the cluster (with the tls URI scheme), Predis will attempt to connect to the other nodes it discovers using the tcp URI scheme (which causes it to fail):

    PHP Fatal error:  Uncaught exception 'Predis\Connection\ConnectionException' with message 'Error while reading line from the server. [tcp://<node-instance>.cache.amazonaws.com:6379]' in /opt/php/php-5.6.8/share/pear/Predis/Connection/AbstractConnection.php:155
    

    Ideally, I would not like to deal with individual nodes and would rather put a DNS entry over the cluster configuration endpoint and only specify that to Predis. This seems like a bug. If it's not, would someone be able to advise me on what is wrong with the setup? Thanks.

    Here's my info:

    • php version: 5.6.8
    • Elasticcache redis driver version: 3.2.6
    • Predis version: 1.1.1
    • OS: ubuntu 14.04
    opened by dfontenot 19
  • v1.1.2 has tests dir export ignored but needed for patches

    v1.1.2 has tests dir export ignored but needed for patches

    In v1.1.2, the tests dir is export-ignore in the .gitattributes file. But, in the composer.json, the files in the tests folder are needed to run the patches. Can you either remove the tests dir from .gitattributes or remove the patch files from composer.json?

    bug 
    opened by dystopianblue 18
Releases(v2.0.3)
  • v2.0.3(Oct 11, 2022)

    • Improved PHP 8.2 support
    • Call is_resource() before reading/writing
    • Added partial support for Redis Stream commands
    • Fixed Sentinel authentication issue
    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Sep 6, 2022)

  • v2.0.1(Sep 4, 2022)

    • Added retry interval to RedisCluster with a default of 10ms
    • Avoid PHP 8.2 warning in Connection\Parameters
    • Fixed Sentinel reconnect issue in long-running PHP processes
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jun 8, 2022)

    • Dropped support for PHP 7.1 and older

    • Accepted values for some client options have changed, this is the new list of accepted values:

      • aggregate: callable returning an aggregate connection.
      • cluster: string value (predis, redis), callable returning an aggregate connection.
      • replication: string value (predis, sentinel), callable returning an aggregate connection.
      • commands: command factory, named array mapping command IDs to PHP classes, callable returning a command factory or a named array.
      • connections: connection factory, callable object returning a connection factory, named array mapping URI schemes to PHP classes, string identifying a supported combination of configurations for the connection factory.
      • prefix: string value, command processor, callable.
      • exceptions: boolean.

      Note that both the cluster and replication options now return a closure acting as initializer instead of an aggregate connection instance.

    • The connections client option now accepts certain string values identifying certain combinations of configurations for the connection factory. Currenlty this is used to provide a short way to configure Predis to load our phpiredis based connection backends simply, accepted values are:

      • phpiredis-stream maps Phpiredis\Connection\PhpiredisStreamConnection to tcp, redis, unix URI schemes.
      • phpiredis-socket maps Phpiredis\Connection\PhpiredisSocketConnection to tcp, redis, unix URI schemes.
      • phpiredis-stream is simply an alias of phpiredis-stream.
    • Added the new Predis\Cluster\Hash\PhpiredisCRC16 class using ext-phpiredis to speed-up the generation of the CRC16 hash of keys for redis-cluster. Predis automatically uses this class when ext-phpiredis is loaded, but it is possible to configure the hash generator using the new crc16 client option (accepted values predis, phpiredis or an hash generator instance).

    • Replication backends now use the role parameter instead of alias in order to distinguish the role of a connection. Accepted values are master, slave and, for redis-sentinel, sentinel. This led to a redesign of how connections can be retrieved from replication backends: the method getConnectionById() now retrieves a connection only by its ID (ip:port pair), to get a connection by its alias there is the new method getConnectionByAlias(). This method is not supported by the redis-sentinel backend due to its dynamic nature (connections are retrieved and initialized at runtime from sentinels) but it is possible to get a single connection from the pool by using its ID. It is also possible to retrive a connection by role using the method getConnectionByRole().

    • The concept of connection ID (ip:port pair) and connection alias (the alias parameter) in Predis\Connection\Cluster\PredisCluster has been separated. This change does not affect distribution and it is safe for existing clusters.

    • Client option classes now live in the Predis\Configuration\Option namespace.

    • Classes for Redis commands have been moved into the new Predis\Command\Redis namespace and each class name mirrors the respective Redis command ID.

    • The concept of server profiles is gone, the library now uses a single command factory to create instances of commands classes. The profile option has been replaced by the commands option accepting Predis\Command\FactoryInterface to customize the underlying command factory. The default command factory class used by Predis is Predis\Command\RedisFactory and it still allows developers to define or override commands with their own implementations. In addition to that, Predis\Command\RedisFactory relies on a convention-over-configuration approach by looking for a suitable class with the same name as the command ID in the Predis\Command\Redis when the internal class map does not contain a class associated.

    • The method Predis\Client::getClientFor($connectionID) has been replaced by getClientBy($selector, $value, $callable = null) which is more flexible as it is not limited to picking a connection from the underlying replication or cluster backend by ID, but allows users to specify a $selector that can be either id (the old behavior), key, slot or command. The client uses duck-typing instead of type-checking to verify that the underlying connection implements a method that matches the specified selector which means that some selectors may not be available to all kinds of connection backends.

    • The method Predis\Client::getConnectionById($connectionID) has been removed.

    • Changed the signature for the constructor of Predis\Command\RawCommand.

    • The Predis\Connection\Aggregate namespace has been split into two separate namespaces for cluster backends (Predis\Connection\Cluster) and replication backends (Predis\Connection\Replication).

    • The method Predis\Connection\AggregateConnectionInterface::getConnection() has been renamed to getConnectionByCommand().

    • The methods switchToMaster() and switchToSlave() have been promoted to be part of Predis\Connection\Replication\ReplicationInterface while the method switchTo($connection) has been removed from it.

    • The method Predis\Connection\Cluster\PredisCluster::executeCommandOnNodes() has been removed as it is possible to achieve the same by iterating over the connection or, even better, over the client instance in order to execute the same command against all of the registered connections.

    • The class Predis\CommunicationException now uses the correct default types for the $message (string) and $code (integer) parameters.

    • The method onConnectionError() in Predis\Connection\AbstractConnection class now passes the second argument as an integer value 0 as its default value instead of null.

    • Support Pub/Sub and Pipelines when using replication

    • The class Predis\Transaction\AbortedMultiExecException now uses the correct default types for the $code (integer) parameter.

    • FIX: using strval in getScanOptions() method, part of Predis\Collection\Iterator\CursorBasedIterator to make sure we retrieve the string value of $this->match and not passing null to strlen() function.

    • FIX: the value returned from getArgument() in isReadOperation() method, part of Predis\Replication\ReplicationStrategy class, is checked to not pass null to sha1 function.

    • FIX: the value returned from getArgument() in parseResponse()method, part of Predis\Command\Redis\SENTINEL class, is checked to not pass null to strtolower() function.

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.1(May 26, 2022)

    • Dropped support for PHP 7.1 and older

    • Accepted values for some client options have changed, this is the new list of accepted values:

      • aggregate: callable returning an aggregate connection.
      • cluster: string value (predis, redis), callable returning an aggregate connection.
      • replication: string value (predis, sentinel), callable returning an aggregate connection.
      • commands: command factory, named array mapping command IDs to PHP classes, callable returning a command factory or a named array.
      • connections: connection factory, callable object returning a connection factory, named array mapping URI schemes to PHP classes, string identifying a supported combination of configurations for the connection factory.
      • prefix: string value, command processor, callable.
      • exceptions: boolean.

      Note that both the cluster and replication options now return a closure acting as initializer instead of an aggregate connection instance.

    • The connections client option now accepts certain string values identifying certain combinations of configurations for the connection factory. Currenlty this is used to provide a short way to configure Predis to load our phpiredis based connection backends simply, accepted values are:

      • phpiredis-stream maps Phpiredis\Connection\PhpiredisStreamConnection to tcp, redis, unix URI schemes.
      • phpiredis-socket maps Phpiredis\Connection\PhpiredisSocketConnection to tcp, redis, unix URI schemes.
      • phpiredis-stream is simply an alias of phpiredis-stream.
    • Added the new Predis\Cluster\Hash\PhpiredisCRC16 class using ext-phpiredis to speed-up the generation of the CRC16 hash of keys for redis-cluster. Predis automatically uses this class when ext-phpiredis is loaded, but it is possible to configure the hash generator using the new crc16 client option (accepted values predis, phpiredis or an hash generator instance).

    • Replication backends now use the role parameter instead of alias in order to distinguish the role of a connection. Accepted values are master, slave and, for redis-sentinel, sentinel. This led to a redesign of how connections can be retrieved from replication backends: the method getConnectionById() now retrieves a connection only by its ID (ip:port pair), to get a connection by its alias there is the new method getConnectionByAlias(). This method is not supported by the redis-sentinel backend due to its dynamic nature (connections are retrieved and initialized at runtime from sentinels) but it is possible to get a single connection from the pool by using its ID. It is also possible to retrive a connection by role using the method getConnectionByRole().

    • The concept of connection ID (ip:port pair) and connection alias (the alias parameter) in Predis\Connection\Cluster\PredisCluster has been separated. This change does not affect distribution and it is safe for existing clusters.

    • Client option classes now live in the Predis\Configuration\Option namespace.

    • Classes for Redis commands have been moved into the new Predis\Command\Redis namespace and each class name mirrors the respective Redis command ID.

    • The concept of server profiles is gone, the library now uses a single command factory to create instances of commands classes. The profile option has been replaced by the commands option accepting Predis\Command\FactoryInterface to customize the underlying command factory. The default command factory class used by Predis is Predis\Command\RedisFactory and it still allows developers to define or override commands with their own implementations. In addition to that, Predis\Command\RedisFactory relies on a convention-over-configuration approach by looking for a suitable class with the same name as the command ID in the Predis\Command\Redis when the internal class map does not contain a class associated.

    • The method Predis\Client::getClientFor($connectionID) has been replaced by getClientBy($selector, $value, $callable = null) which is more flexible as it is not limited to picking a connection from the underlying replication or cluster backend by ID, but allows users to specify a $selector that can be either id (the old behavior), key, slot or command. The client uses duck-typing instead of type-checking to verify that the underlying connection implements a method that matches the specified selector which means that some selectors may not be available to all kinds of connection backends.

    • The method Predis\Client::getConnectionById($connectionID) has been removed.

    • Changed the signature for the constructor of Predis\Command\RawCommand.

    • The Predis\Connection\Aggregate namespace has been split into two separate namespaces for cluster backends (Predis\Connection\Cluster) and replication backends (Predis\Connection\Replication).

    • The method Predis\Connection\AggregateConnectionInterface::getConnection() has been renamed to getConnectionByCommand().

    • The methods switchToMaster() and switchToSlave() have been promoted to be part of Predis\Connection\Replication\ReplicationInterface while the method switchTo($connection) has been removed from it.

    • The method Predis\Connection\Cluster\PredisCluster::executeCommandOnNodes() has been removed as it is possible to achieve the same by iterating over the connection or, even better, over the client instance in order to execute the same command against all of the registered connections.

    • The class Predis\CommunicationException now uses the correct default types for the $message (string) and $code (integer) parameters.

    • The method onConnectionError() in Predis\Connection\AbstractConnection class now passes the second argument as an integer value 0 as its default value instead of null.

    • The class Predis\Transaction\AbortedMultiExecException now uses the correct default types for the $code (integer) parameter.

    • FIX: using strval in getScanOptions() method, part of Predis\Collection\Iterator\CursorBasedIterator to make sure we retrieve the string value of $this->match and not passing null to strlen() function.

    • FIX: the value returned from getArgument() in isReadOperation() method, part of Predis\Replication\ReplicationStrategy class, is checked to not pass null to sha1 function.

    • FIX: the value returned from getArgument() in parseResponse()method, part of Predis\Command\Redis\SENTINEL class, is checked to not pass null to strtolower() function.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.10(Jan 5, 2022)

    • FIX: Avoid PHP 8.1 deprecation notices in Session/Handler
    • FIX: Fixed "Cannot use object of type Predis\Response\Error as array" error in Connection/Aggregate/SentinelReplication
    Source code(tar.gz)
    Source code(zip)
  • v1.1.9(Oct 5, 2021)

  • v1.1.8(Sep 29, 2021)

  • v1.1.7(Apr 4, 2021)

    • FIX: with the phpiredis-based connection backends, failed pipelines led to spurious responses returned after reconnecting to Redis because the underlying reader was not properly reset by discarding buffered replies after disconnecting (ISSUE #363).
    • FIX: removed cweagans/composer-patches dev dependency and apply patches using post-update-cmd script.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.6(Sep 11, 2020)

    That was fast, but we had a bug in v1.1.5 so we needed to release a fix ASAP.

    FIX: reverted support for sentinels authentication implemented in v1.1.5 as it was bugged (see ISSUE #658), sorry for the trouble. This is now postponed as it requires a more thorough investigation.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.5(Sep 10, 2020)

    Here we have a new patch release!

    NOTE: We are still missing handlers for commands added in Redis 4, 5 and 6. We will get on par eventually, in the meanwhile you can define your own ones or use Predis\Client::executeRaw(). Read this post for details about how to properly implement support for new commands if you would like to add missing ones and share your work with us by creating pull requests, contributions are always greatly appreciated!

    • NOTE intentionally commented out, please read the release notes for v1.1.6 ~~FIX: authentication for sentinels is now supported, previously it was not possible to specify a password for sentinels as its value was stripped during initialization because sentinels did not support authentication until Redis 5. Please note that with the current implementation each sentinel must have its own password parameter set in the parameters list despite this password is the same for all sentinels (read how requirepass works on the Redis docs). In this case you should avoid using the global parameters client option used to set default parameters for every connection created by Predis as this would end up using the same password even when connecting to actual Redis nodes. We are investiganting how to make it easier to specify the required password to access sentinels only once instead of repeating it for each sentinel.~~

    • FIX: the username is now correctly retrieved from the userinfo fragment of the URI when using the redis scheme and a username:password pair is present. Values retrieved from the userinfo fragment always override the ones specified in username and password if those fields are present in the query string.

    • FIX: Predis\Connection\WebdisConnection was unable to connect to Webdis when using an IPv4 address in the URL and this is probably due to some change in cURL internals since the last time we tested it.

    • FIX: an exception is thrown when passing FALSE or any value evaluating to FALSE to the replication client option. This was supposed to be unsupported, in fact it actually breaks client initialization and raises a PHP warning. Now the user is alerted with an InvalidArgumentException and a proper message. (PR #381).

    Source code(tar.gz)
    Source code(zip)
  • v1.1.4(Aug 31, 2020)

    Here is a new patch release for v1.1 with more improvements and fixes.

    NOTE: We are still missing handlers for commands added in Redis 4, 5 and 6. We will get on par eventually, in the meanwhile you can define your own ones or use Predis\Client::executeRaw(). Read this post for details about how to properly implement support for new commands if you would like to add missing ones and share your work with us by creating pull requests, contributions are always greatly appreciated!

    • The client can now handle ACL authentication when connecting to Redis 6, just pass both username and password to connection parameters and Predis switches to using the augmented variant of AUTH:

      // When using an URI string for parameters:
      $client = new Predis\Client('tcp://127.0.0.1?username=myuser&password=mypassword');
      
      // When using a named array for parameters:
      $client = new Predis\Client([
          'username' => 'myuser',
          'password' => 'mypassword',
      ]);
      

      As usual Redis servers protected only by a password can still be accessed with just the password parameter. See the Redis documentation for more details about Redis ACLs.

    • FIX: NULL or zero-length string values in password and database do not trigger spurious AUTH and SELECT commands anymore when connecting to Redis.

      // Won't trigger `AUTH` and `SELECT`:
      $client = new Predis\Client('tcp://127.0.0.1?password=&database=');
      
      // Won't trigger `AUTH` and `SELECT`:
      $client = new Predis\Client([
          'password' => null,
          'database' => '',
      ]);
      

      This fix addresses some old issues with certain libraries and frameworks (see ISSUE #436).

      Empty connection parameters do not make much sense anyway so, in the next major release, any field containing NULL or a zero-length string will be stripped away when converting URI strings and named arrays to instances of Predis\Connection\Parameters.

    • FIX: SORT now always triggers a switch to the master node in replication configurations instead of just when the STORE modifier is specified. The reason for this change is that SORT is always considered to be a write operation and it actually fails with a -READONLY error response when executed against a replica node (ISSUE #554).

    • FIX: using foreach() on a client instance when it is connected to a single Redis server does not throw an exception anymore but the iteration will run for just one loop returning a new client for the underlying single-node connection (ISSUE #552, PR #556).

      $client = new Predis\Client('tcp://127.0.0.1');
      
      foreach ($client as $clientNode) {
          // Iterates just once, does not throw an exception anymore.
      }
      

      Using foreach() actually makes sense when using aggregate connection backends for client-side sharding or redis-cluster but there is no reason (and it is wrong anyway) to throw an exception in Predis\Client::getIterator() when the client is connected to a single server.

    • FIX: Predis\Cluster\Distributor\HashRing::addNodeToRing() was calculating the hash required for distribution by using crc32() directly instead of the method Predis\Cluster\Hash\HashGeneratorInterface::hash() implemented by the class itself. This fix does not have any impact on existing cluster deployments using client-side sharding based on this distributor simply because it does not take any external hash generators so distribution is not going to be affected.

    • Improved @method annotations for methods responding to Redis commands defined by Predis\ClientInterface and Predis\ClientContextInterface (PR #456 and PR #497, other fixes applied after further analysys).

    Source code(tar.gz)
    Source code(zip)
  • v1.1.3(Aug 18, 2020)

    • Ensure compatibility with PHP 8.
    • Moved repository from github.com/nrk/predis to github.com/predis/predis.
    • FIX: Moved cweagans/composer-patches dependency to require-dev.
    • FIX: Include PHPUnit .patch files in exports.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.2(Aug 11, 2020)

    Predis is under new management. Read the announcement and checkout the roadmap 🚀

    If you (or your business) would like to support the development of this fantastic library and ensure it's bright future, please use the GitHub Sponsor button 🙏🏻

    Changes

    • FIX: pure CRC16 implementation failed to calculate the correct hash when the input value passed to the hash() method is an integer (PR #450).
    • FIX: make PHP iterator abstractions for ZSCAN and HSCAN working with PHP 7.2 due to a breaking change, namely the removal of each() (PR #448).
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Jun 17, 2016)

    This is a patch release of Predis v1.1 that fixes a few bugs affecting the previous release. As usual you can read the CHANGELOG for a schematic list of the changes.

    Bug fixes

    • FIX: password and database from the global parameters client option were still being applied to sentinels connections making them fail (sentinels do not understand the AUTH and SELECT commands) (PR #346).
    • FIX: when a sentinel instance reports no slave for a service, invoking connect() on the redis-sentinel connection backend should fall back to the master connection instead of failing (ISSUE #342).
    • FIX: the two connection backends based on ext-phpiredis has some kind of issues with the GC and the internal use of closures as reader callbacks that prevented connections going out of scope from being properly collected and the underlying stream or socket resources from being closed and freed. This should not have had any actual effect in real-world scenarios due to the lifecycle of PHP scripts, but we fixed it anyway (ISSUE #345).

    Other links

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 2, 2016)

    Introduction

    This is a minor release of Predis packed with new features and various improvements of existing ones. As usual you can read the CHANGELOG for a schematic list of the changes. Thanks to anyone who provided feedback, especially on the new features, and proposed changes implemented in this release! Starting today we also have a chat room on Gitter, for now it's kind of an experiment but we'll see on the long run if it'll prove to be useful.

    IMPORTANT: if you are using "predis/predis": "dev-master" in composer.json then replace the requirement with tagged releases in the v1.1 branch as soon as possible! Starting today the master branch will host the development of the next major version of Predis, the first few commits containing some major breaking changes will land there in a matter of days meaning that if you won't replace dev-master your applications may (and most likely will) fail all of sudden.

    NOTE: speaking of Predis v2.0 we are aiming to bump the minimum required version of PHP to 5.5.9 (most likely to happen) and drop PEAR for distribution (still to be decided). The v1.1 branch will be maintaned for fixes so if you are stuck with PHP 5.3 and 5.4 you don't have too much to worry about for a while. If you have anything to say on the matter please join the discussion by leaving a comment or a reaction on #335, we need your feedback!

    New features

    • Support for redis-sentinel is finally baked into Predis! As usual configuring the client is easy, it's just a matter of providing a list of sentinel servers and configure the client accordingly:

      $parameters = ['tcp://127.0.0.1:5380', 'tcp://127.0.0.1:5381', 'tcp://127.0.0.1:5382'];
      
      $options = [
          'replication' => 'sentinel', // use the appropriate replication backend
          'service' => 'mymaster',     // provide a service name for discovery
      ];
      
      $client = new Predis\Client($parameters, $options);
      

      See replication_sentinel.php for a complete example.

    • Redis servers protected by SSL-encrypted connections can be accessed by using the tls or rediss scheme in connection parameters along with SSL-specific options in the ssl parameter (array):

      // Parameters in the form of a named array
      $parameters = [
          'scheme' => 'tls',
          'host'   => '127.0.0.1',
          'ssl'    => [
              'cafile' => '/path/to/redis.pem',
              'verify_peer_name' => true,
          ],
      ];
      
      // Parameters in the form of an URI string
      $parameters = 'tls://127.0.0.1?ssl[cafile]=/path/to/redis.pem&ssl[verify_peer_name]=1';
      
    • Implemented the ability to specify default connection parameters for aggregate connections with the new parameters client option. These parameters augment the usual user-supplied connection parameters (but do not take the precedence over them) when creating new connections and they are mostly useful when the client is using aggregate connections such as redis-cluster and redis-sentinel as these backends can create new connections on the fly based on responses and redirections from Redis:

      $parameters = ['tcp://127.0.0.1:6381', 'tcp://127.0.0.1:6382', 'tcp://127.0.0.1:6383'];
      
      $options = [
          'cluster' => 'redis',
          // New connections to Redis will be created using the same following parameters:
          'parameters' => ['database' => 5, 'password' => $secret],
      ];
      
      $client = new Predis\Client($parameters, $options);
      
    • Predis\Client implements the IteratorAggregate interface making it is possible to iterate over traversable aggregate connections and get a new client instance for each Redis node:

      $client = new Predis\Client($parameters, ['cluster' => 'redis']);
      
      foreach ($client as $nodeClient) {
          $nodeClient->flushdb();  // executes FLUSHDB on each node of the cluster
      }
      

    Changes

    • The default server profile for the client now targets Redis 3.2.
    • Responses to the following list of commands are not casted into booleans anymore but instead the original integer value of the response is returned: SETNX, MSETNX, SMOVE, SISMEMBER, HSET, HSETNX, HEXISTS, PFADD, EXISTS, MOVE, PERSIST, EXPIRE, EXPIREAT, RENAMENX. This change does not have a significant impact unless when using strict comparisons (=== and !==) on the returned value.
    • Using unix:///path/to/socket in URI strings to specify a UNIX domain socket file is now deprecated in favor of the format unix:/path/to/socket (note the lack of the double slash after the scheme) and will not be supported starting with the next major release.
    • The client throws exceptions when Redis returns any kind of error response to initialization commands (the ones being automatically sent when a connection is established, such as SELECT and AUTH when database and password are set in connection parameters) regardless of the value of the exception option.
    • Iterating over an instance of Predis\Connection\Aggregate\RedisCluster will return all the connections mapped in the slots map instead of just the ones in the in-memory pool. This change makes it possible, when the slots map is retrieved from Redis, to iterate over all of the master nodes in the cluster. When the use of CLUSTER SLOTS is disabled via the useClusterSlots() method, the iteration returns only the connections with slots ranges associated in their parameters or the ones initialized by -MOVED responses in order to make the behaviour of the iteration consistent between the two modes of operation.

    Improvements

    • Non-boolean string values passed to the persistent connection parameter can be used to create different persistent connections to the same host-port pair:

      // $parameters1 and $parameters2 will create two different persistent connections:
      $parameters1 = "tcp://127.0.0.1:6379?persistent=first";
      $parameters2 = "tcp://127.0.0.1:6379?persistent=second";
      

      Note that this feature was already present in Predis but required both persistent and path to be set as illustrated by #139, this change was needed to prevent confusion with how path is used to select a database when using the redis scheme.

    • Various improvements to Predis\Connection\Aggregate\MasterSlaveReplication (the "basic" replication backend, not the new one based on redis-sentinel):

      • When the client is not able to send a read-only command to a slave because the current connection fails or the slave is resyncing (-LOADING response returned by Redis), the backend discards the failed connection and performs a new attempt on the next slave. When no other slave is available the master server is used for read-only commands as last resort.
      • It is possible to discover the current replication configuration on the fly by invoking the discover() method which internally relies on the output of the command INFO REPLICATION executed against the master server or one of the slaves. The backend can also be configured to do this automatically when it fails to reach one of the servers.
      • Implemented the switchToMaster() and switchToSlave() methods to make it easier to force a switch to the master server or a random slave when needed.

    Other links

    Source code(tar.gz)
    Source code(zip)
  • v1.0.4(May 30, 2016)

    This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

    IMPORTANT: Predis v1.1.0 is going to be released in just a few days, this minor release will ship with various improvements and the much-awaited support for redis-sentinel. Soon after that the master branch will host the development of Predis v2.0 and the first major change will be a bump of the minimum required version of PHP to 5.5.9, please read about it here and leave a comment if you have something to say on the matter as the decision has not been finalized as of yet.

    Improvements

    • Added a new profile for Redis 3.2 with its new commands: HSTRLEN, BITFIELD, GEOADD, GEOHASH, GEOPOS, GEODIST, GEORADIUS, GEORADIUSBYMEMBER. The default server profile for Predis is still the one for Redis 3.0 so you must set the profile client option to 3.2 when initializing the client in order to be able to use them when connecting to Redis 3.2.
    • redis-cluster: when the connection to a specific node fails the client tries to connect to another node in order to refresh the slots map and perform a new attempt to execute a command.
    • redis-cluster: connections to nodes can now be preassigned to non-contiguous slot ranges via the slots parameter using a comma separator (e.g. tcp://127.0.0.1:6379?slots=0-5460,5500-5600,11000)

    Bug fixes

    • FIX: Predis\Collection\Iterator\HashKey was returning corrupted values when iterating hash keys containing integer fields (PR #330, ISSUE #331).
    • FIX: Predis\Connection\StreamConnection and Predis\Protocol\Text\RequestSerializer do not fail when serializing commands with holes in their arguments (e.g. [0 => 'key:0', 2 => 'key:2']) just like the phpiredis-based connection backends (ISSUE #316).

    Other links

    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(Jul 30, 2015)

    This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

    IMPORTANT NOTICE: this release supersedes v1.0.2.

    Bug fixes

    • FIX: the previous release introduced a severe regression on HHVM preventing the client from connecting to Redis using IPv4 addresses. Code running on the standard PHP interpreter is unaffected. (#269)

    Other links

    Source code(tar.gz)
    Source code(zip)
  • v1.0.2(Jul 30, 2015)

    This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

    IMPORTANT NOTICE: this release has been superseded by v1.0.3 due to a severe regression affecting only HHVM preventing the client from connecting to Redis using IPv4 addresses. Code running on the standard PHP interpreter is unaffected.

    Improvements

    • IPv6 is fully supported.
    • The redis scheme can be used in URI strings and is considered an alias of tcp but the rules applied when parsing the URI follow the provisional registration document published by IANA while the usual Predis-specific rules still apply when using tcp and other schemes.
    • Implemented some missing commands: HSTRLEN (Redis >= 3.2), ZREVRANGEBYLEX (Redis >= 2.8) and MIGRATE (>= 2.6).
    • The ZADD modifiers NX|XX, CH, INCR introduced in Redis 3.0.2 can also be used with the simplified signature of this command where scores and members are passed as a named array.

    Bug fixes

    • FIX: Predis\Configuration\Options must not trigger the autoloader when values are strings (#257).
    • FIX: BITPOS was not defined in the key-prefix processor (#265) and in the replication strategy.

    Notes

    • Predis v1.1.0 should follow in just a few weeks and, being a minor release, will deliver more than just bugfixes or minor improvements. The addition of support for redis-sentinel is a long-standing feature request that will hopefully find its way into the library (see #131) and some major and much needed improvements to redis-cluster are also scheduled (see #173). As usual any help is more than appreciated so feel free to hop on these issues for sharing ideas and advices, or even contribute with a pull request.

    Other links

    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jul 30, 2015)

    This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

    Improvements

    • Added the BITPOS command to the server profile for Redis 2.8 (pull request by @nicchap).
    • It is now possible to specify a timeout for read/write operations also when using UNIX domain sockets with Predis\Connection\StreamConnection which is the default connection class based on PHP's streams (pull request by @srhnsn).

    Bug fixes

    • A bug prevented Predis\Collection\Iterator\SortedSetKey to work correctly when iterating over sorted sets containing integer members (see #216).
    • Applied a workaround for a bug in old versions of PHP < 5.3.9 affecting inheritance (see 99f4312a6feb2cadaf83b008d006c1720f580723).
    • Prevent E_NOTICE messages from being emitted when requesting empty or unexistent info sections using INFO.

    Notes

    • Due to a bug in HHVM <= 3.4.0, it is not possible to use Predis\PubSub\Consumer and Predis\Monitor\Consumer when running under Facebook's runtime for now. You can find more details in the discussion on #231 (thanks @rubensayshi for the catch!) which also provides an hack to work around this issue until the next release of HHVM will ship with their bug fixed.

    Downloads

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jun 1, 2016)

    This is not only a new and major release of Predis, but it is an important milestone because it represents the first stable release in terms of API (both public and internal). Lots of changes have been made to improve the overall design and code quality while optimizing the library as much as possible.

    You can consult the CHANGELOG for more details about changes and bug fixes introduced in this release.

    IMPORTANT NOTE: we switched to PSR-4 for autoloading but PEAR packaging still uses PSR-0 for obvious reasons, the conversion is performed when generating the package using bin/create-pear. We do not plan to support installation through PEAR indefinitely, but we will stick with it for a few more releases.

    Introduction

    One of the purposes of this new release was to make use of better names for classes, interfaces and namespaces so we ended up with shorter fully-qualified names and a better organization of namespaces. While these changes can be quite radical in certain cases, the truth is that they will most likely affect only code-bases where developers made use of certain classes to extend the library with custom features. Those simply using Predis as a client will not probably notice any difference. Just to make a few examples (for the rest, see the CHANGELOG):

    • The Predis\Option namespace is now Predis\Configuration.
    • The Predis\Command\AbstractCommand class is now Predis\Command\Command.
    • The Predis\Command\ScriptedCommand class is now Predis\Command\ScriptCommand.
    • Aggregate connections (cluster, replication) are in the Predis\Connection\Aggregate namespace.
    • Classes representing status and error responses are in the Predis\Response namespace.

    Obviously it is not only a matter of renaming or moving things around, the overall internal design of Predis has been dramatically improved and now certain aspects of the library (such as clustering) are more solid and more open to extension. Last but not least a lot of work has been done to keep performances in check, resulting in less overhead when initializing client instances and no difference at runtime in raw numbers compared to v0.8.x despite the additional flexibility.

    Improvements

    • @method in docblocks: while this is not strictly a feature, now Predis ships with @method tags for Predis\ClientInterface and Predis\ClientContextInterface (pipelines, transactions) so you can leverage autocompletion and inspection while coding with your favourite IDE. This should be a much welcome addition for many developers since it has been requested many times in the last couple of years.

    • Server profiles: the default one is now 3.0 (obviously targeting Redis 3.0.0). It is safe to switch now since the are no breaking changes between Redis 2.8 and 3.0. At the same time, the server profile for Redis 1.2 has been removed since it is relatively ancient stuff.

    • New commands: added SENTINEL to the server profile for Redis 2.6 and PUBSUB to the server profile for Redis 2.8. Please note that you will not find CLUSTER and other commands used by redis-cluster in the server profile for Redis 3.0. Internally they are used as raw commands, they may be added in the future though as soon as Redis 3.0 becomes stable.

    • Raw commands: now they can be sent simply by providing an array of arguments (comprising of the command ID) to Predis\Client::executeRaw(). This method skips key prefixing (and more generally, any command processor) and response parsing, so it always returns responses as documented on the Redis website. It is also possible to tell when Redis returns an error thanks to the second optional argument populated by reference with a boolean value:

      $response = $client->executeRaw(["SET", "foo", "bar"]); // string(2) "OK"
      $response = $client->executeRaw(["STRLEN", "foo"]);     // int(3)
      
      // When $iserror is TRUE, $response contains the error string.
      $response = $client->executeRaw(["LPUSH", "foo", "bar"], &$iserror);
      
    • Changes for ZRANGE-like commands using WITHSCORES: Predis used to return the member and score pair as an array of [$member, $score] when using the WITHSCORES modifier with ZRANGE, ZREVRANGE, ZRANGEBYSCORE and ZREVRANGEBYSCORE. Now the raw response is parsed to a named array so members and their scores can be accessed as $member => $score.

      $members = $client->zrange("key", 0, -1, "withscores");
      // Predis v0.8 (old): [["member1", "score1"], ...]
      // Predis v1.0 (new): ["member1" => "score1", ...]
      

      The output of ZSCAN has also been changed accordingly in order to reflect the same output, while Predis\Collection\Iterator\SortedSetKey is not affected by this change. NOTE: the ordering of the original response is still preserved thanks to how PHP internally works with named arrays.

    • Redis responses: status responses are now returned as instances of Predis\Response\Status and carry their original payload string. +OK is then no more returned to the client as a boolean TRUE, but since a status response can be transparently casted to string one can do $response == "OK" which is also more akin to how Redis replies to clients. Instances of common status responses such as +OK or +QUEUED are shared internally in order to avoid wasting memory. Another change regards custom response parsers in commands (see Predis\Command\CommandInterface::parseResponse()) which are now applied inside consumer classes such as Predis\Client.

    • Client options: the fully reworked Predis\Configuration\Options class now has the ability to lazily initialize values using objects that respond to __invoke() and it works even for custom options defined by the user. This is an example of a complex and modular set of options where standard and user-defined options are mixed together, and the ones regarding cluster are initialized lazily only when needed by the client:

      $client = new Predis\Client($parameters, [
        'exceptions'  => true,
        'connections' => [
          'tcp'  => 'Predis\Connection\PhpiredisStreamConnection',
        ],
        'distributor' => function () {
          return new Predis\Cluster\Distributor\KetamaRing();
        },
        'strategy'    => function ($options) {
          return new Predis\Cluster\PredisStrategy($options->distributor);
        },
        'cluster'     => function ($options) {
          $strategy = $options->strategy;
          $cluster = new Predis\Connection\Aggregate\PredisCluster($strategy);
      
          return $cluster;
        },
        'profile'     => function ($options, $option) {
          $profile = $options->getDefault($option);
          $profile->defineCommand("luascript", "Nrk\Command\LuaScriptCommand");
      
          return $profile;
        },
      ]);
      

      In addition to the client options already supported by v0.8, the new aggregate option overrides both cluster and replication and can be used to initialize an aggregate connection taking full control over its initialization (the return type must be Predis\Connection\AggregateConnectionInterface).

    • Cluster with client-side sharding: Predis now uses the same rules defined by the redis-cluster specification when dealing with empty hash-tags {} in keys, so upgrading Predis might affect the distribution of your already-deployed cluster. If you want to make sure that you will not be affected by this change, you can extend Predis\Cluster\PredisStrategy to override the extractKeyTag($key) method and configure the client to use your strategy like this:

      class OldPredisStrategy extends Predis\Cluster\PredisStrategy
      {
        protected function extractKeyTag($key)
        {
          if (false !== $start = strpos($key, '{')) {
            if (false !== $end = strpos($key, '}', $start)) {
              $key = substr($key, ++$start, $end - $start);
            }
          }
      
          return $key;
        }
      }
      
      $client = new Predis\Client($nodes, [
        "cluster" => function () {
          $strategy = new OldPredisStrategy();
          $cluster = new Predis\Connection\Aggregate\PredisCluster($strategy);
      
          return $cluster;
        },
      ]);
      

      This is possible because, starting with v1.0, Predis\Connection\Aggregate\PredisCluster accepts an instance of Predis\Cluster\StrategyInterface as the only argument in its constructor instead of Predis\Cluster\Distributor\DistributorInterface. The distributor, on the other hand, is now wrapped by Predis\Cluster\PredisStrategy.

    • Pipeline options: Predis\Client::pipeline() now accepts options to choose which kind of pipeline object should be initialized among the ones supported by Predis:

      • atomic: wraps the pipeline in a MULTI / EXEC transaction (Predis\Pipeline\Atomic).
      • fire-and-forget: does not read back responses (Predis\Pipeline\FireAndForget).
    • Transaction options: while Predis\Transaction\MultiExec still supports cas, watch and retry, there are also a couple of changes:

      • exceptions: overrides the value of $options->exceptions provided in client options.
      • on_retry: this option has been removed.
    • Key prefixing: while changes in this case are completely transparent to users, the prefixing logic has been moved from command classes to the key prefix processor returned by $options->prefix. Commands are recognized by their IDs and developers can define or override the handlers used to prefix keys based on their arguments. This makes it possible to prefix keys also when using the generic Predis\Command\RawCommand class.

    Dropped stuff:

    • Obsolete methods: Predis\Client::multiExec() and Predis\Client::pubSub() have been removed after having been deprecated in v0.8.5. The new names for these methods are respectively Predis\Client::transaction() and Predis\Client::pubSubLoop().
    • Iterable multibulk responses: the commonly used Predis\Connection\StreamConnection does not support them anymore and iterable_multibulk has been removed from the default connection parameters. You can still use them with Predis\Connection\CompositeStreamConnection (it is slower, but makes use of a pluggable protocol system) and the classes implementing multibulk iterators are available in the Predis\Response\Iterator namespace.
    • Pipeline executors: they are no more needed after the changes in Predis\Pipeline\Pipeline.

    What's next?

    Having finally reached v1.0 is a great milestone considering that Predis has been around for 5 years now, but there is obviously more to come: v1.1 will ship with new features and the most important ones will most likely be support for redis-sentinel with replication and support for slaves in redis-cluster. Minor versions will be released more frequently compared to the past, now that the library is considered stable in terms of design and API.

    There is also another aspect that should really be addressed: documentation. Predis simply does not have enough documentation covering useful features or the inner parts of the library. I plan to resume the initial efforts started in the documentation branch but frankly I hope to receive also some external contributions.

    All in all I am happy with this release and even though it took 7 months to ship (way more than what I originally planned, mostly due to some busy months) the result is more than satisfactory in terms of quality. Big thanks to everyone who has shared their feedbacks or contributed with suggestions and code!

    KTHXBYE.

    Downloads

    Source code(tar.gz)
    Source code(zip)
  • v0.8.7(Aug 1, 2014)

    This is a maintenance release for the 0.8 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

    New features

    Redis commands

    • Added the profile alias 3.0 for Redis 3.0, but 2.8 is still the default one.
    • Added COMMAND to the server profile for Redis 2.8. This command is actually available since Redis 2.8.13 so it will return a -ERR when executed against older versions of Redis.

    Redis Cluster

    The new default for redis-cluster when the client receives a -MOVED response is to fetch an updated slots map automatically from the node target of the persistent redirection. Thanks to this change you can now feed the client constructor with only a few of the nodes in your cluster without the need to use a more complex configuration, so even if your cluster have - let's say - 10 nodes you can still use only a couple or more connection parameters:

    $client = new Predis\Client(
        ["tcp://10.0.0.1:6379", "tcp://10.0.0.1:6380"],
        ["cluster" => "redis"]
    );
    

    Internally the client fetches the slots map using the new CLUSTER SLOTS command made available since Redis 3.0.0b7, which means your nodes must be upgraded to the most recent beta release of Redis (but you should do it anyway since it is beta software).

    PubSub

    Implemented PING in our PUB/SUB loop abstraction for Redis >= 3.0.0b8. You can now ping the connection with an optional payload directly from the loop instance, and receive back a PONG message:

    foreach ($pubSubLoop as $message) {
        switch ($message->kind) {
            case "subscribe":
                $pubSubLoop->ping("hello!");
                break;
    
            case "pong":
                echo "Pong message with payload $message->payload\n";
                break;
        }
    }
    

    Bug fixes

    • The patch applied in v0.8.6 to fix #180 introduced a regression affecting read/write timeouts in Predis\Connection\PhpiredisStreamConnection so we had to apply a further fix which, unfortunately, absolutely requires PHP 5.4+ meaning that read/write timeouts will be ignored from now on PHP 5.3.

    Downloads

    Source code(tar.gz)
    Source code(zip)
  • v0.8.6(Jul 15, 2014)

    This is a maintenance release for the 0.8 series with some improvements to existing features. What follows is an overview of the changes and bug fixes introduced in this new release, details are also available in the CHANGELOG.

    New features

    Redis commands

    Improvements

    Redis Cluster

    When coupled with Redis >= 3.0.0b1 you can now use key hash tags (e.g. key:{hash:tag}) to force certain keys to be stored on the same node, just like it happens with the good old client-side sharding. See commit ba2ffb6.

    Bug fixes

    • Minor tweaks to make this version of Predis compatible with HHVM >= 2.4.0.
    • Using Redis sentinel does not break the parsing of responses to INFO anymore. See issue #154 and commit f4a950b.
    • INCRBYFLOAT is now handled as expected in cluster and replication configurations. See issue #159 and commit c2ae1c6.
    • Fixed the parsing procedure for the output of CLUSTER NODES when fetching the slots map from a node and redis-cluster has slaves in its configuration. See issue #165 and commit e148dc8. NOTE: the new CLUSTER SLOTS command is the proper way to fetch the slots map now, but we'll stick with the old method for this patch release of v0.8 while v1.0.0 will rely on it by default.
    • Prevent a stack overflow when iterating over large Redis collections using our abstraction for cursor-based iterators. See issue #182 and commit b77da84.
    • Properly discards transactions when the server immediately returns an error response (e.g. -OOM or -ERR on invalid arguments for a command) instead of a +QUEUED response. See issue #187 and commit 74817b5.

    Future development

    Believe me, Predis v1.0.0 is on its way and will be released really soon... this time I mean it for real ;-) That said, v0.8 will still be maintaned for a while with a few more patch releases mainly targeted at improving redis-cluster support as much as possible and fixing issues.

    Additional notes

    Downloads

    Source code(tar.gz)
    Source code(zip)
  • v0.8.5(Jan 16, 2014)

    This is a maintenance release for the 0.8 series with some improvements to existing features. What follows is an overview of the changes and bug fixes introduced in this new release, details are also available in the CHANGELOG.

    New features

    Redis commands

    • Added a new server profile for Redis 2.8. The default value for the profile client option still targets Redis 2.6 and the dev profile now targets Redis 3.0.
    • New commands added to the 2.8 profile: SCAN, SSCAN, ZSCAN and HSCAN to the server profile for Redis 2.8.

    Collection iterators

    The new cursor-based iterator commands available starting from Redis 2.8 make it possible to iterate Redis collections without blocking the server but developers still need to implement some logic in their applications to fully leverage them. To ease the usage of such commands we added some abstractions in the Predis\Collection namespace in the form of plain old PHP iterators, making it possible to fully iterate Redis collections in your PHP code with something as simple as foreach.

    Redis do not have a cursor-based iterator for lists but we added an abstraction with Predis\Collection\Iterator\ListKey based on LRANGE that tries to mimic a similar behavior while not being exactly the same thing.

    You can find some examples here.

    Raw commands

    It is possible to execute raw commands using Predis\Command\RawCommand and a variable list of command arguments. The main difference with the usual approach is that input arguments are not filtered and complex responses are not parsed, which also means arguments must follow the exact same signature of the command as defined by Redis. Obviously there is no need to create and register a new class to use them:

    $command = Predis\Command\RawCommand::create('SET', 'foo', 'bar');
    $response = $client->executeCommand($command);
    

    Executing commands in this way can be useful to implement internal features, when the user-specified server profile is not accessible or when you need to make sure that your code will not be affected by different argument filtering or response parsing implementations.

    This feature will be further improved in the next major release.

    Improvements

    Redis Cluster

    Some aspects of our abstraction for Redis Cluster have been dramatically improved or fixed while others (such as silent handling of connection failures) will be addressed in later patch releases.

    • The ASKING command is now correctly sent automatically upon -ASK redirections.
    • Updated slots maps can be fetched from nodes thanks to the CLUSTER NODES command. By default this is a manual operation but it can be enabled to get automatically done upon -MOVED redirections.
    • It is possible to specify a common set of connection parameters that are applied to connections created on the fly upon redirections to nodes that are not part of the initial pool.

    Query string parsing for connection parameters

    URI parsing now relies on parse_str for the query string part which has a slightly smaller overhead when the number of fields in the querystring grows. Furthermore:

    • Parsing does not break when value of a field contains one or more =.
    • Repeated fieldnames using [] produce an array of values.
    • Empty or incomplete key=value pairs result in an empty string for key.

    Deprecations

    A couple of methods of Predis\Client are now marked as deprecated and will be removed in the next major release:

    • Predis\Client::multiExec(): superseded by Predis\Client::transaction().
    • Predis\Client::pubSub(): superseded by Predis\Client::pubSubLoop(). This change was needed due to the recently introduced PUBSUB command in Redis 2.8.

    Future development

    Aside from a few more tweaks aimed at improving support for the upcoming Redis Cluster there is not much to add or change in the current v0.8 branch. The library is very stable judging by the history of issues opened during the last months so you can expect a couple of patch releases for v0.8 until Redis 3.0 but nothing more. The good news is that the release of the next major version is imminent and Predis will finally hit v1.0! The transition from v0.8 to v1.0 will bring a lot of breaking changes required to polish the API of the library and its internals, but the actual impact on your code (that is, if you plan to upgrade) may vary depending on your kind of usage: in simple scenarios where Predis is used as a mere client without relying on its extensibility, it is pretty much possible that nothing will change for you.

    You can already start playing with it by requiring "predis/predis": "dev-master" in composer.json. Predis v1.0.0 is planned to be released on the same day of the first beta of Redis Cluster, 10th February 2014.

    Additional notes

    Downloads

    Source code(tar.gz)
    Source code(zip)
  • v0.8.4(Jul 27, 2013)

    This is a maintenance release for the 0.8 series shipping mostly bug fixes. What follows is an overview of the changes and bug fixes introduced in this new release, details are also available in the CHANGELOG.

    Bug fixes and changes

    Redis commands

    Scripted commands and key prefixing

    Predis failed to handle falling back from EVALSHA to EVAL using scripted commands with no arguments defined for KEYS[] when the client was configured to use key prefixing. (see related pull request)

    Failing host reported in exception messages

    When a connection error occurs, such as when Predis is not able to connect to a server, the exception message now includes the incriminated Redis server: Connection refused [tcp://127.0.0.1:3322]. This can be handy to debug or log errors especially when using multiple nodes in a replication or cluster configuration. (see related pull request)

    DispatcherLoop

    The pub/sub-based DispatcherLoop class has been fixed to properly work when using a prefixed client instance. (see related pull request)

    PhpiredisConnection

    This connection backend now uses gethostbynamel to handle hostnames with multiple IP addresses associated and randomly choses one of them. This is mostly useful to distribute the load on multiple Redis instances configured as read-only slaves sitting behind one single hostname. (see related pull request)

    Additional notes

    Downloads

    Source code(tar.gz)
    Source code(zip)
  • v0.8.3(Jul 16, 2014)

    Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.

    This is a maintenance release for the 0.8 series shipping some new features and minor micro-optimizations. What follows is an overview of the new features and changes introduced in this new release, for a more in-depth list of changes please see the CHANGELOG.

    New features and changes

    CLIENT SETNAME and CLIENT GETNAME

    Thanks to Raphael Stolt's pull request you can now use CLIENT SETNAME and CLIENT GETNAME.

    New stream-based phpiredis connection backend

    We've had a connection backend based on the phpiredis extension for quite some time now, but it required the socket extension to be loaded in order to work. Now there's a new connection backend which still relies on phpiredis to parse and serialize the Redis protocol, but internally uses PHP's native streams. One of the benefits of using streams is that they support persistent connections when used with plain FastCGI or php-fpm processes. Client configuration to make use of this connection backend is the same as usual, you just need to specify the Predis\Connection\PhpiredisStreamConnection class:

    <?php
    $client = new Predis\Client('tcp://127.0.0.1', array(
        'connections' => array(
            'tcp'  => 'Predis\Connection\PhpiredisStreamConnection',
            'unix' => 'Predis\Connection\PhpiredisStreamConnection',
        ),
    );
    

    TCP_NODELAY with stream-based connections (PHP >= 5.4.0 only)

    One of the historic downsides of using stream-wrapped sockets has always been the impossibility of tinkering with socket options, but luckily for us the introduction of socket_import_stream() in PHP 5.4 removed this limitation. This make it possible to set the TCP_NODELAY socket option to enable or disable Nagle's algorithm using the tcp_nodelay connection parameter:

    <?php
    $client = new Predis\Client('tcp://127.0.0.1?tcp_nodelay=0');
    

    You can effectively set any kind of socket option by yourself in your library or application's code with something like:

    <?php
    $client = new Predis\Client('tcp://127.0.0.1');
    $socket = socket_import_stream($client->getConnection()->getResource());
    socket_set_option($socket, SOL_TCP, TCP_NODELAY, 0);
    

    Callable objects for$parameters in client constructor

    Additionally to strings, arrays or even instances of Predis\Connection\ConnectionInterface, now the first argument of Predis\Client::__construct() can accept callable objects returning instances of Predis\Connection\ConnectionInterface. This may appear as an unnecessary addition, but it can reveal itself useful to create custom and self-contained solutions to handle complex configuration scenarios. As an (admittedly) extreme example, we relied on this feature to wrap the code needed to use client-side sharding to distribute keys among virtual nodes of replicated Redis instances without further changing the library's code.

    Minor non-breaking change in Lua scripting abstraction

    When instructing scripted commands to use all the arguments to populate the ARGV table and leave KEYS empty on Lua's side, developers were required to return FALSE (strictly boolean) from getKeysCount() in their command implementation. This choice didn't make much sense and now you can simply return 0. This change does not break existing code since 0 == FALSE in PHP.

    Changes in redis-cluster distribution

    Salvatore recently started working again on redis-cluster (that alone is an awesome news!) and commited a change raising the number of hash slots used for distribution, from 4096 to 16384. Our aggregated connection for redis-cluster has been updated accordingly, so pay attention when upgrading both Redis and Predis if you were brave enough having something based on it.

    Additional notes

    Downloads

    Useful links

    Source code(tar.gz)
    Source code(zip)
  • v0.8.2(Jul 16, 2014)

    Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.

    This is a maintenance release for the 0.8 series. What follows is an overview of the new features and fixes introduced in this new release, for a more in-depth list of changes please see the CHANGELOG.

    New features and changes

    Fix for response parsing in pipelines

    The main reason for this new patch release is to fix a bug introduced right before releasing v0.8.0 that prevented complex responses from Redis from being parsed correctly in command pipelines as reported on this issue. This bug didn't affect correctness of the data stored or returned by Redis, but prevented replies to certain commands such as HGETALL from being parsed by the client before returning to the user's code.

    Predis-based session handler

    A new class Predis\Session\SessionHandler has been added to provide an easy way to use Predis as a backend to store PHP's sessions on Redis. This new class is mainly intended for PHP >= 5.4 since it implements SessionHandlerInterface but it can be used with PHP 5.3 if a polyfill for this interface is provided by you or an external package in your dependencies (such as symfony/http-foundation just to name one).

    <?php
    $client = new Predis\Client('tcp://127.0.0.1', array('prefix' => 'sessions:'));
    $handler = new Predis\Session\SessionHandler($client);
    $handler->register();
    

    See a more exhaustive example.

    Predis service provider for Silex

    Along with this release, the official service provider for Silex has been finally updated to use Predis v0.8 with a new version bump that brings some breaking changes when dealing with multiple clients configuration. These changes was necessary to better fit with the boot mechanism for service providers that was introduced a few months ago in Silex.

    Additional notes

    Downloads

    Useful links

    Source code(tar.gz)
    Source code(zip)
  • v0.8.1(Jul 16, 2014)

    Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.

    This is a maintenance release for the 0.8 series. What follows is an overview of the new features and fixes introduced in this new release, for a more in-depth list of changes please see the CHANGELOG.

    New features and changes

    Client options

    When using callables with client options accepting them, Predis now passes the current option instance as their second argument making it possible to get the default value for that option:

    <?php
    $options = array(
        'profile'  => function ($options, $option) {
            $profile = $option->getDefault($options);
            $profile->defineCommand('test', 'My\Command\TestCommand');
    
            return $profile;
        },
    );
    
    $client = new Predis\Client('tcp://127.0.0.1', $options);
    

    Now you can use a callable with the connections option to initialize the instance of Predis\Connection\ConnectionFactoryInterface that will be used internally by the client to create the underlying connection:

    <?php
    $options = array(
        'connections' => function ($options, $option) {
            $factory = $option->getDefault($options);
    
            if (extension_loaded('phpiredis')) {
                $factory->define('tcp', 'Predis\Connection\PhpiredisConnection');
                $factory->define('unix', 'Predis\Connection\PhpiredisConnection');
            }
    
            return $factory.
        },
    );
    

    Client-side sharding based on node alias

    There was this long-standing feature request that never got a decent solution shipped within the library in order to support named connections (distribution of nodes is based on their alias instead of the host:port pair), but now we have a generalized way to do that supported by both Predis\Cluster\Distribution\HashRing and Predis\Cluster\Distribution\KetamaPureRing and consists of passing a callable to the second argument of their constructors:

    <?php
    use Predis\Cluster\Distribution\HashRing;
    use Predis\Connection\PredisCluster;
    
    $options = array(
        'cluster' => function ($options) {
            $replicas = HashRing::DEFAULT_REPLICAS;
    
            $nodehash = function ($connection) {
                return $connection->getParameters()->alias;
            }
    
            $hashring = new HashRing($replicas, $nodehash);
            $cluster  = new PredisCluster($hashring);
    
            return $cluster;
        },
    );
    

    As you can see you can decide which kind of value to return from your callback, but keep in mind that everything will be casted to string by our hashring implementation.

    Fix for edge case in Lua scripting abstraction

    When leveraging the scripted commands abstraction Predis always tries to optimize things by using EVALSHA which, on the other hand, could fail with a -NOSCRIPT error if the Lua script referred by its SHA1 hash has not been cached by Redis yet. In these cases Predis automatically retries by issuing an EVAL command with the same arguments in addition to the whole Lua script body, but due to this bug the client wasn't using the original parseResponse() method from the initial command instance to parse the response.

    Documentation

    Thanks to dominics' initial push we have finally started with the long-overdue task of documenting Predis using Sphinx. Documentation is being written and integrated into our separate documentation branch, so make sure to open your pull requests against this branch if you plan to contribute.

    Phpiredis extension

    Thanks to the work of seppo0010 we were able to add the support for a PHP extension to parse the Redis protocol in a more efficient way since Predis v0.7.0, but now that the ownership of the phpiredis repository has been transferred to me I plan to tweak it and add new features from time to time (though the idea is to keep it minimal and simple). Having said that, I am by no means a C developer so help and contributions will be highly welcome and appreciated!

    Additional notes

    Downloads

    Useful links

    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Jul 16, 2014)

    Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.

    This is a major release and it is not backwards compatible with the v0.7.x series due to the fact that some namespaces and classes have been renamed or moved and a few parameters and client options have been modified. What follows is an overview of the new features and major changes introduced with this new release, for a more in-depth list of changes please read the CHANGELOG.

    New features and changes

    Support for Redis versions and features

    The default server profile is now 2.6 which is the current stable branch of Redis while the dev profile targets Redis 2.8. Please note that starting with Redis 2.6 the output of INFO is splitted into sections and, to accomodate this change, Predis returns nested named arrays when using the 2.6 profile.

    Connection parameters and client options

    There are some changes for connection parameters.

    • connection_async is now async_connect
    • connection_timeout is now timeout
    • connection_persistent is now persistent
    • throw_errors has been removed, replaced by the new exceptions client option.

    Please note that using the old parameter names with this new version does not raise any notice.

    As an example, the following client configuration for Predis v0.7.x:

    $parameters = "tcp://127.0.0.1?connection_async=1&connection_timeout=5&connection_persistent=1&throw_errors=1";
    $client = new Predis\Client($parameters);
    

    starting with Predis v0.8.0 must be changed into:

    $parameters = "tcp://127.0.0.1?async_connect=1&timeout=5&persistent=1"
    $client = new Predis\Client($parameters, array('exceptions' => true));
    

    Additionally, the second parameter of the constructor of Predis\Client does not accept strings or instances of Predis\Profile\ServerProfileInterface like in the past but the server profile must be set by using the profile client option explicitly:

    $client = new Predis\Client('tcp://127.0.0.1', '2.4');                      // Wrong
    $client = new Predis\Client('tcp://127.0.0.1', array('profile' => '2.4'));  // OK
    

    Redis Cluster

    While redis-cluster will not be available until Redis 3.0, Predis already ships with a first working implementation of the logic needed to use this amazing new feature. Configuring the client is simply a matter of passing the list of nodes in the same exact order as they are specified when using redis-trib and setting the cluster client option to redis:

    $nodes = array('tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3');
    $client = new Predis\Client($nodes, array('cluster' => 'redis'));
    

    Obviously you can rest assured that the good old way of creating a cluster of Redis nodes simply by relying on client-side sharding is still in place and is the default behavior of the client.

    Server-side scripting with Lua

    Predis supported Redis scripting since v0.7.0 but our high-level abstraction built on top of EVAL and EVALSHA (we call it a scripted command) has been improved to save bandwidth by using the latter by default and falling back transparently to the former when required (that is, when Redis replies to EVALSHA with a -NOSCRIPT error).

    Going asynchronous with Predis\Async

    Crazy? Maybe, but at least now you can thanks to Predis\Async. This separate project shares the same style and feel of Predis by reusing some of its core classes and is built on top of React to provide a fully-asynchronous implementation of a Redis client. The library is considered experimental and subject to changes in its API, but it already works and can cooperate seamlessy with any other library that makes use of the core event loop abstraction provided by React/EventLoop.

    Future development

    While this new major release admittedly do not add much features to the plate aside from early support for redis-cluster and a separate project for a fully-asynchronous client, the internals of Predis have been extensively reworked to make the library and its core parts even more easy to extend and reuse, but also with some optimizations put in place. We are at a point in which further changes to the internal architecture of Predis should not be needed for a while, or at least not until we decide to drop compatibility with PHP 5.3 and rewrite stuff to make use of new features introduced in PHP 5.4, which means that we can proceed with experimenting a few ideas such as having core parts of the library implemented in C as an optional PHP extension. Right now you can already use phpiredis to speed thins up, but we can definitely do better that that.

    In a more immediate future, aside from addressing eventual bugs the next patch releases in the v0.8.x series will also see the addition of some missing features such as an abstration to deal with redis-sentinel.

    Additional notes

    Downloads

    Useful links

    Source code(tar.gz)
    Source code(zip)
  • v0.7.3(Jul 16, 2014)

    Predis is a flexible and feature-complete PHP client library for Redis.

    This is a maintenance release for the 0.7 series. What follows is an overview of the new features introduced in this new release. For a more in-depth list of changes please see the CHANGELOG.

    New features and changes

    New commands in the Redis 2.6 server profile

    Two new commands have been added to Redis 2.6: BITOP and BITCOUNT.

    Scripting abstraction improvements

    It is now possible to use negative numbers in the getKeysCount() method to tell Predis\Commands\ScriptedCommand to calculate the actual number of keys used to populate the KEYS array for EVAL starting from the end of the arguments list. You can read this comment for a description of a use case.

    We also fixed a bug in Predis\Commands\ServerEvalSHA::getScriptHash().

    Additional notes

    Downloads

    Related projects

    Useful links

    Source code(tar.gz)
    Source code(zip)
Owner
Predis
A flexible and feature-complete Redis client for PHP.
Predis
A flexible and feature-complete Redis client for PHP.

Predis A flexible and feature-complete Redis client for PHP 7.2 and newer. ATTENTION: you are on the README file of an unstable branch of Predis speci

Predis 7.3k Jan 3, 2023
This package is considered feature-complete, and is now in security-only maintenance mode

laminas-soap This package is considered feature-complete, and is now in security-only maintenance mode, following a decision by the Technical Steering

Laminas Project 46 Dec 18, 2022
A Symfony Feature Flag Bundle which easily allows you to configure and use your favorite feature flag provider.

Metro Markets FF Metro Markets FF is a Feature Flag Symfony Bundle. It easily allows you to configure and use your favorite feature flag provider. Ins

METRO Markets 14 May 23, 2022
ExpressionEngine is a flexible, feature-rich, free open-source content management platform that empowers hundreds of thousands of individuals and organizations around the world to easily manage their web site.

ExpressionEngine CMS ExpressionEngine is a mature, flexible, secure, free open-source content management system. It is beloved by designers for giving

ExpressionEngine 412 Dec 27, 2022
Complete Pipedrive API client for PHP

Complete Pipedrive API client for PHP Contribute by referral code / link This won't take much time. You could use my referral code or link to get up t

Israel Ortuño 155 Dec 7, 2022
Async Redis client implementation, built on top of ReactPHP.

clue/reactphp-redis Async Redis client implementation, built on top of ReactPHP. Redis is an open source, advanced, in-memory key-value database. It o

Christian Lück 240 Dec 20, 2022
A complete Login and Register page using a Mysql Database and php

Login With Mysql A complete Login and Register page using a Mysql Database ?? Built with ⚙️ ?? Description A login with Frontend, Backend and Database

Marc Medrano 1 Nov 5, 2021
Complete Login and Registration system using HTML, CSS, JAVASCRIPT, BOOTSTRAP, PHP and MYSQL

Complete Login and Registration system using HTML, CSS, JAVASCRIPT, BOOTSTRAP, PHP and MYSQL

JehanKandy 11 Jul 13, 2022
Complete Login and Registration System with HTML CSS Bootstrap PHP and MYSQL

Complete-Login-and-Registration-System Complete Login and Registration System with HTML CSS Bootstrap PHP and MYSQL for .sql file run xampp server ope

JehanKandy 10 Jul 13, 2022
Lightweight and feature-rich PHP validation and filtering library. Support scene grouping, pre-filtering, array checking, custom validators, custom messages. 轻量且功能丰富的PHP验证、过滤库。支持场景分组,前置过滤,数组检查,自定义验证器,自定义消息。

PHP Validate 一个简洁小巧且功能完善的php验证、过滤库。 简单方便,支持添加自定义验证器 支持前置验证检查, 自定义如何判断非空 支持将规则按场景进行分组设置。或者部分验证 支持在进行验证前对值使用过滤器进行净化过滤内置过滤器 支持在进行验证前置处理和后置处理独立验证处理 支持自定义每

Inhere 246 Jan 5, 2023
Laravel Auth is a Complete Build of Laravel 8 with Email Registration Verification, Social Authentication, User Roles and Permissions, User Profiles, and Admin restricted user management system.

Laravel Auth is a Complete Build of Laravel 8 with Email Registration Verification, Social Authentication, User Roles and Permissions, User Profiles, and Admin restricted user management system. Built on Bootstrap 4.

Jeremy Kenedy 2.8k Dec 31, 2022
A complete and fully-functional implementation of the Jade template language for PHP

Tale Jade for PHP Finally a fully-functional, complete and clean port of the Jade language to PHP — Abraham Lincoln The Tale Jade Template Engine brin

Talesoft 91 Dec 27, 2022
A complete, simple and powerful database framework written in PHP

BaseSQL BaseSQL is a complete database framework written in PHP. It was built to accelerate projects development by handle database connections and qu

Willian Pinheiro 2 Sep 21, 2021
phpDocumentor is an application that is capable of analyzing your PHP source code and DocBlock comments to generate a complete set of API Documentation

phpDocumentor What is phpDocumentor? phpDocumentor is an application that is capable of analyzing your PHP source code and DocBlock comments to genera

phpDocumentor 3.7k Jan 3, 2023
PHP Kafka client is used in PHP-FPM and Swoole. PHP Kafka client supports 50 APIs, which might be one that supports the most message types ever.

longlang/phpkafka Introduction English | 简体中文 PHP Kafka client is used in PHP-FPM and Swoole. The communication protocol is based on the JSON file in

Swoole Project 235 Dec 31, 2022
Feature plugin to count CSS and JS assets loaded by the theme on front-end and display recommandations in Site Health

=== Site Health - Audit Enqueued Assets === Contributors: audrasjb, whodunitagency Tags: site health, performance audit, performance test, assets, scr

Jb Audras 3 Nov 5, 2021
LaraEstimate is a complete Dynamic Estimates/Quotes System made with Laravel 7 and VueJS.

LaraEstimate LaraEstimate is a complete Dynamic Estimates/Quotes System made with Laravel 7 and VueJS. The system has the following features: Allows t

Tiago S. P. Rodrigues 133 Dec 12, 2022
A complete stack for running Symfony 5 into Docker containers using docker-compose tool and with Certbot for the HTTPS certificate.

?? Docker + PHP 7.4 + MySQL8.0 + Nginx + Certbot(HTTPS) + Symfony 5 Boilerplate ?? Edited from https://github.com/ger86/symfony-docker version -> http

null 6 Nov 9, 2022
Laravel Podcast Manager is a complete podcast manager package for Laravel 5.3+ that enables you to manage RSS feeds for your favorite podcasts and listen to the episodes in a seamless UI.

laravelpodcast | A Laravel podcast manager package - v0.0.8 Introduction Laravel Podcast Manager is a complete podcast manager package for Laravel 5.3

Jeremy Kenedy 22 Nov 4, 2022
swoole and golang ipc, use goroutine complete swoole coroutine

swoole and golang ipc demo swoole process module exec go excutable file as sider car, use goroutine complete swoole coroutine hub.php <?php require '

null 2 Apr 17, 2022