/php-react-memcached

Asynchronous Memcached PHP Client for ReactPHP ecosystem

Primary LanguagePHPMIT LicenseMIT

ReactPHP Memcached Client

Asynchronous Memcached PHP Client for ReactPHP ecosystem.

Build Status Scrutinizer Code Quality Maintainability Test Coverage StyleCI

Table of Contents

Installation

Dependencies

Library requires PHP 5.6.0 or above.

The recommended way to install this library is via Composer. New to Composer?

See also the CHANGELOG for details about version upgrades.

composer require seregazhuk/react-memcached

Quick Start

require '../vendor/autoload.php';

use seregazhuk\React\Memcached\Factory;

$loop = React\EventLoop\Factory::create();
$client = Factory::createClient($loop);

$client->set('example', 'Hello world');

$client->get('example')->then(function ($data) {
    echo $data . PHP_EOL; // Hello world
});

// Close the connection when all requests are resolved
$client->end();

$loop->run();

See other examples.

Server address

When creating a client via the factory you can specify server address as a second argument:

$client = Factory::createClient($loop, 'localhost:11222');

If the address is not specified the client uses default localhost:11211.

Asynchronous Execution

For each Memcached command a client has a method. All commands are executed asynchronously. The client stored pending requests and once it receives the response from the server, it starts resolving these requests. That means that each command returns a promise. When the server executed a command and returns a response, the promise will be resolved with this response. If there was an error, the promise will be rejected.

Retrieval Commands

Get

Get value from key:

$client
    ->get('some-key')
    ->then(function ($data) {
        echo "Retreived value: " . $data . PHP_EOL; 
    });

Storage Commands

For $flags you can use PHP MEMCACHE_COMPRESSED constant to specify on-the-fly compression. If the value was not stored indicate because condition for add or replace commands wasn’t met, or the item was in a delete queue, the promise will be rejected with FailedCommandException.

Set

Store key/value pair in Memcached:

$client
    ->set('some-key', 'my-data')
    ->then(function () {
        echo "Value was stored" . PHP_EOL;
    });
    
// advanced: with compression and expires in 30 seconds
$client
    ->set('some-key', 'my-data', MEMCACHE_COMPRESSED, 30)
    ->then(function () {
        echo "Value was stored" . PHP_EOL;
    });    

Add

Store key/value pair in Memcached, but only if the server doesn’t already hold data for this key:

$client
    ->add('name', 'test')
    ->then(function() {
        echo "The value was added" . PHP_EOL;
    });
    
    
// advanced: with compression and expires in 30 seconds
$client
    ->add('name', 'test', MEMCACHE_COMPRESSED, 30)
    ->then(function() {
        echo "The value was added" . PHP_EOL;
    });    

Replace

Store key/value pair in Memcached, but only if the server already hold data for this key:

$client
    ->replace('name', 'test')
    ->then(function(){
        echo "The value was replaced" . PHP_EOL;
    });
 
// advanced    
$client
    ->replace('name', 'test', $flags, $exptime)
    ->then(function(){
        echo "The value was replaced" . PHP_EOL;
    });    

Delete Command

Delete value by key from Memcached. If the key doesn't exist or has been deleted the promise rejects with FailedCommandException:

$client
    ->delete('name')
    ->then(function(){
        echo "The value was deleted" . PHP_EOL;
});

Increment/Decrement Commands

Increment

Increment value associated with key in Memcached, item must exist, increment command will not create it. The limit of increment is the 64 bit mark. If key is not found, the promise will be rejected with FailedCommandException:

$client
    ->incr('var', 2)
    ->then(
        function($data){
            echo "New value is: " . $data . PHP_EOL;
        }, 
        function(FailedCommandException $e) {
            echo "Key not found" . PHP_EOL;
        });

Decrement

Decrement value associated with key in Memcached, item must exist, decrement command will not create it If you try to decrement a value bellow 0, value will stay at 0. If key is not found, the promise will be rejected with FailedCommandException:

$client
    ->decr('var', 2)
    ->then(
        function($data){
            echo "New value is: " . $data . PHP_EOL;
        },
        function(FailedCommandException $e) {
            echo "Key not found" . PHP_EOL;
        });

If value not found, the promise will be rejected with FailedCommandException.

Touch Command

The touch command is used to update the expiration time of an existing item without fetching it. If the key doesn't exist or has been deleted the promise rejects with FailedCommandException:

$client
    ->touch('var', $exp)
    ->then(
    function($data){
        echo "The value was toched". PHP_EOL;
    },
    function(FailedCommandException $e) {
        echo "Key not found" . PHP_EOL;
    });

Statistics Command

This command can return an array of various stats:

$client
    ->stats()
    ->then(function($result){
        print_r($result);
        /*
        Array
        (
            [pid] => 666
            [uptime] => 180660
            [time] => 1508342532
            ... 
            [lru_bumps_dropped] => 0
        )
        */
    });

Misc Commands

Flush all

Flush the server key/value pairs (invalidating them) after an optional [] period:

$client
    ->flushAll()
    ->then(function() {
        echo "Everything was flushed" . PHP_EOL;
    });

Version

Return the Memcached server version:

$client
    ->version()
    ->then(function($result) {
        echo "Memcached version: $result" . PHP_EOL; // Memcached version: 1.5.0
     });

Verbosity

Change the verbosity output of Memcached server:

$client
    ->verbosity(2)
    ->then(function($result) {
        echo "Verbosity was changed to 2" . PHP_EOL;
    });

Connection Closing

End()

To close the connection call end() method on the client. The client waits till all pending requests are resolved and then closes the connection. All new requests to the client will be rejected with ConnectionClosedException exception.

Close()

If you want to force the closing and don't want to wait for pending requests to be resolved, call close() method. It immediately closes the connection and rejects all pending requests with ConnectionClosedException exception.

Events Handling

You can register event handlers for some client's events.

close

When the connection to Memcached server is closed, the close event is emitted. You can listen to this event to catch connection failures:

$client->on('close', function () {
    // handle closed connection
});

error

When an error occurs in the connection, the client emits error event and passes an exception with the problem description:

$client->on('error', function (Exception $e) {
    // handle error
});

For example you can handle broken connections like this:

$client->on('error', function (ConnectionClosedException $e) {
    // handle broken connection
});

Errors Handling

All exceptions that are thrown by the client or are used to reject the promises extend from the base seregazhuk\React\Memcached\Exception\Exception class.

For example, if you call an unknown Memcached command the promise will be rejected with WrongCommandException:

$client
    ->unknown()
    ->then('var_dump', function(WrongCommandException $e){
        echo $e->getMessage() . PHP_EOL; // Unknown command: unknown
});

When the connection is broken all pending promises will be rejected with ConnectionClosedException exception.