<?php 
 
/* 
 * This file is part of the Predis package. 
 * 
 * (c) Daniele Alessandri <[email protected]> 
 * 
 * For the full copyright and license information, please view the LICENSE 
 * file that was distributed with this source code. 
 */ 
 
require __DIR__.'/shared.php'; 
 
// This is an implementation of an atomic client-side ZPOP using the support for 
// check-and-set (CAS) operations with MULTI/EXEC transactions, as described in 
// "WATCH explained" from http://redis.io/topics/transactions 
// 
// First, populate your database with a tiny sample data set: 
// 
// ./redis-cli 
// SELECT 15 
// ZADD zset 1 a 2 b 3 c 
// 
// Then execute this script four times and see its output. 
// 
 
function zpop($client, $key) 
{ 
    $element = null; 
    $options = array( 
        'cas' => true,      // Initialize with support for CAS operations 
        'watch' => $key,    // Key that needs to be WATCHed to detect changes 
        'retry' => 3,       // Number of retries on aborted transactions, after 
                            // which the client bails out with an exception. 
    ); 
 
    $client->transaction($options, function ($tx) use ($key, &$element) { 
        @list($element) = $tx->zrange($key, 0, 0); 
 
        if (isset($element)) { 
            $tx->multi();   // With CAS, MULTI *must* be explicitly invoked. 
            $tx->zrem($key, $element); 
        } 
    }); 
 
    return $element; 
} 
 
$client = new Predis\Client($single_server); 
$zpopped = zpop($client, 'zset'); 
 
echo isset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL; 
 
 |