Predis - a PHP interface to Redis

This documentation is based on Predis 1.1.2-dev.

Source Markdown files are available on GitHub or directly at this path.

Please submit corrections via GitHub.

Documentation map

Calling Redis commands

$oldValue = $predis->getset('skey', 'newvalue');
var_dump($oldValue);    //=> string(3) "foo"

Command reference: supported Redis commands (GETSET, SORT, HGET, etc.) and their arguments.

The Client class API.

Connection configuration

$connections = [
  ['database' => 3, 'alias' => 'primary'],
  ['host' => 'backupredis.example.com', 'scheme' => 'tls'],
];

$predis = new Predis\Client($connections);

Using a connection string:

$predis = new Predis\Client('unix:///var/run/redis.sock?database=5');

The connections option: backends (PhpiredisStreamConnection) and their schemes (tcp, unix, etc.).

Predis options

$options = ['exceptions' => false];
$predis = new Predis\Client([], $options);

Configuration reference: supported Predis options for Client constructor.

Default connection parameters

$connections = [
  ['alias' => 'primary'],
  ['port' => 6380, 'alias' => 'backup'],
];

$options = [['parameters' => ['host' => 'redis.example.com', 'scheme' => 'tls']];

$predis = new Predis\Client($connections, $options);

The above is equivalent to:

$connections = [
  [
    'host' => 'redis.example.com',
    'scheme' => 'tls',
    'alias' => 'primary',
  ],
  [
    'host' => 'redis.example.com',
    'scheme' => 'tls',
    'port' => 6380,
    'alias' => 'backup',
  ],
];

$predis = new Predis\Client($connections);

The parameters option.

Pipelining

Basic:

$res = $predis->pipeline(function ($p) {
  $p->set('skey', 'v');
  $p->hmset('hkey', ['k' => 'v', 'k2' => 'v2']);
  $p->get('skey');
  $p->get('skey2');
});

// $res has 4 members - one per each command ran.

Combined with a transaction (options):

$res = $predis->pipeline(['atomic' => true], function ($p) {
  ...
});

Custom transaction nesting:

$res = $predis->pipeline(function ($p) {
  $p->get('notintrans');

  $p->multi();
  $p->set('skey', 'intrans');
  $p->exec();

  $p->get('againnotintrans');
});

// $res has 5 members, with array 4th (EXEC) containng 1 member.

Using fluent interface:

$res = $predis->pipeline(['atomic' => true])
  ->get('skey')
  ->set('skey', 'value')
  ->execute();

Transactions

Basic:

$res = $predis->transaction(function ($t) {
  $t->get('skey');
  $t->hset('hkey', 'k', 'v');
});

// $res has 2 members.

Faining on key(s) changes (WATCH) with up to two retries:

try {
  $res = $predis->transaction(['watch' => 'wkey', 'retry' => 2], function ($t) {
    ...
  });
} catch (Transaction\AbortedMultiExecException $e) {
  die("Still couldn't save the changes after 3 attempts.");
}

Compare-And-Swap:

$res = $predis->transaction(['watch' => 'wkey', 'cas' => true], function ($t) {
  $value = $t->get('wkey');
  $t->multi();
  $t->set('wkey', $value.'foo');
});

Using fluent interface:

$res = $predis->transaction(['exceptions' => false])
  ->set('k1', 'v1')
  ->set('k2', 'v2')
  ->execute();

// With 'exceptions' unset, failed commands will return an ErrorInterface object instead of throwing ServerException.

Pub/Sub subscription

Basic:

$predis->pubSubLoop(['subscribe' => 'chan'], function ($l, $msg) {
  if ($msg->payload === 'Q') {
    return false;
  } else {
    echo "$msg->payload on $msg->channel", PHP_EOL;
  }
});

Using a consumer object:

$l = $predis->pubSubLoop(['subscribe' => 'chan']);

foreach ($l as $msg) {
  if ($msg->payload === 'unsub') {
    $l->unsubscribe('chan');
  } elseif ($msg->payload === 'psub') {
    $l->psubscribe('chan:*');
  } elseif ($msg->payload === 'Q') {
    $l->stop();
  }
}

echo 'pub/sub has stopped.';

Using per-channel callbacks:

$l = predis->pubSubLoop();
$dl = new Predis\PubSub\DispatcherLoop($l);

$dl->attachCallback('chan1', function ($payload) {
  echo "Got $payload on chan1.", PHP_EOL;
});

$dl->attachCallback('ctlchan', function ($payload) use ($dl) {
  echo "Received a message on ctlchan, stopping.";
  $dl->stop();
});

$dl->defaultCallback(function ($msg) {
  echo "Received a message on $msg->channel.", PHP_EOL;
});

$l->psubscribe('foo:*');

$l->run();

Iterating over keys and members

All keys in a database (SCAN):

$it = new Predis\Collection\Iterator\Keyspace($predis);

foreach ($it as $key) {
  echo "Found a key named '$key'", PHP_EOL;
}

Hash fields (HSCAN):

$it = new Predis\Collection\Iterator\HashKey($predis, 'hkey');

foreach ($it as $key => $value) {
  echo "Found a field '$key', value '$value' in hash key 'hkey'", PHP_EOL;
}

Set members (SSCAN):

$it = new Predis\Collection\Iterator\SetKey($predis, 'setkey');

foreach ($it as $member) {
  echo "Found a member '$member' in set key 'setkey'", PHP_EOL;
}

Sorted set members (ZSCAN):

$it = new Predis\Collection\Iterator\SortedSetKey($predis, 'zkey');

foreach ($it as $member => $score) {
  echo "Found a member '$member', score '$score' in sorted set key 'zkey'", PHP_EOL;
}

List values (emulation with LRANGE):

$it = new Predis\Collection\Iterator\ListKey($predis, 'lkey');

foreach ($it as $member) {
  echo "Found a member '$member' in list key 'lkey'", PHP_EOL;
}

Registering Lua scripts

class EchoScript extends Predis\Command\ScriptCommand {
  function getScript() {
    return 'return ARGV[1]';
  }
}

$predis->getProfile()->defineCommand('echolua', 'EchoScript');

echo $predis->echolua('foo');
  //=> foo

The ScriptCommand Class.

Session handler

$h = new Session\Handler($predis);
$h->register();
session_start();

The Session\Handler class: using Redis for storing session data.

Other topics

Syntax conventions

Function definitions include arguments type hinting similar to those used in the PHP manual. In cases no type hint is present, a string type - str - is implied. Usually if an invalid type is given there will be a PHP error or implicit coersion so don't do that.

Sometimes argument $name is omitted and only its type hint is left for clarity. This is often done with object arguments: SomeInterface $some is written as just SomeInterface.

The $key argument always contains name of a Redis key entry such as foo:123. $src and $dest arguments are similar but additionally indicate that the operation will take data from ($src) or put data into ($dest) them.

If arguments are omitted with an ellipsis: brpop(...) - they are entirely dictated by another source indicated by the See reference in the description.

Many functions are variadic, i.e. accepting arbitrary number of arguments. Some functions even have several "variadic" argument groups. Variability is indicated by the [...] pattern (where square brackets mean optional data as per standard BNF notation). For example:

eval($script, $numKeys[, $key[...]][, $arg[...]]);

The definition above contains 2 variadic groups: $key and $arg. Examples of proper invocation:

eval('s', 1, 'k', 'v', 'v2');
eval('s', 1, 'k');
eval('s', 0, 'v', 'v2');
eval('s', 0);

Examples in the Commands section omit object reference from method invokaction for clarity. Thus, the above example in real code looks like this:

$predis = new Predis;
$predis->eval('s', 1, 'k', 'v', 'v2');
...

All examples assume their base namespace as Predis so that Command\HashGet refers to Predis\Command\HashGet. In some cases class names are further reduced since most are unique Predis-wise. Thus ConnectionException refers to Predis\Connection\ConnectionException.

The $predis variable in the examples refers to a previously set up Predis\Client object.