Install the Package:
composer require php-riak/riak-client
Note: Ensure your project uses PHP 5.4+ (Laravel 5.8+ requires PHP 7.2+, so test compatibility or use a polyfill).
Configure the Client:
use Riak\Client\RiakClientBuilder;
$builder = new RiakClientBuilder();
$client = $builder
->withNodeUri('http://riak-node-1:8098') // Replace with your Riak node URI
->withNodeUri('http://riak-node-2:8098') // Add more nodes for HA
->build();
Tip: Use environment variables (e.g., .env) for node URIs in Laravel.
First Use Case: Store and Fetch Data
// Store a value
$namespace = new \Riak\Client\Core\Query\RiakNamespace('bucket_type', 'bucket_name');
$location = new \Riak\Client\Core\Query\RiakLocation($namespace, 'user:123');
$object = new \Riak\Client\Core\Query\RiakObject();
$object->setValue(json_encode(['name' => 'John', 'email' => 'john@example.com']));
$object->setContentType('application/json');
$store = \Riak\Client\Command\Kv\StoreValue::builder($location, $object)
->withW(2) // Wait for 2 nodes to acknowledge
->withPw(1) // Allow 1 node to fail
->build();
$client->execute($store);
// Fetch the value
$fetch = \Riak\Client\Command\Kv\FetchValue::builder($location)
->withR(1) // Read from 1 node
->withNotFoundOk(true)
->build();
$result = $client->execute($fetch);
$data = json_decode($result->getValue(), true);
Laravel Integration:
Bind the client to the service container in config/app.php:
'providers' => [
// ...
App\Providers\RiakServiceProvider::class,
],
Create a service provider:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Riak\Client\RiakClientBuilder;
class RiakServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('riak.client', function () {
$builder = new RiakClientBuilder();
return $builder
->withNodeUri(config('riak.nodes.0'))
->withNodeUri(config('riak.nodes.1'))
->build();
});
}
}
Add Riak config to config/riak.php:
return [
'nodes' => [
'http://riak-node-1:8098',
'http://riak-node-2:8098',
],
];
StoreValue with RiakObject for data serialization.
$object = new \Riak\Client\Core\Query\RiakObject();
$object->setValue(json_encode($data));
$object->setContentType('application/json');
FetchValue with withR() to control read consistency.
$fetch = \Riak\Client\Command\Kv\FetchValue::builder($location)
->withR(2) // Stronger consistency
->build();
DeleteValue with withW() for write quorum.
$delete = \Riak\Client\Command\Kv\DeleteValue::builder($location)
->withW(2)
->build();
Implement ConflictResolver for merging conflicting writes:
use Riak\Client\Resolver\ConflictResolver;
use Riak\Client\Core\Query\RiakList;
class JsonMergeResolver implements ConflictResolver
{
public function resolve(RiakList $siblings)
{
$merged = [];
foreach ($siblings as $sibling) {
$data = json_decode($sibling->getValue(), true);
$merged = array_merge_recursive($merged, $data);
}
return new \Riak\Client\Core\Query\RiakObject(
json_encode($merged),
'application/json'
);
}
}
Register the resolver in the builder:
$builder->withConflictResolver('application/json', new JsonMergeResolver());
Query buckets using secondary indexes (e.g., user_email):
use Riak\Client\Command\Kv\FetchValues;
$query = \Riak\Client\Core\Query\RiakQuery::builder()
->withBucketType('user')
->withBucket('profiles')
->withSecondaryIndex('user_email', 'john@example.com')
->build();
$fetch = FetchValues::builder($query)
->withMaxResults(10)
->build();
$results = $client->execute($fetch);
Execute custom MapReduce jobs:
$map = 'function(map) { emit(this.email, this.name); }';
$reduce = 'function(reduce, values) { return Array.sum(values); }';
$query = \Riak\Client\Core\Query\RiakQuery::builder()
->withBucketType('user')
->withBucket('profiles')
->withMapReduce($map, $reduce)
->build();
$result = $client->execute(\Riak\Client\Command\Kv\Query::builder($query)->build());
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Riak\Client\Core\Query\RiakNamespace;
use Riak\Client\Core\Query\RiakLocation;
class RiakUser extends Model
{
protected $primaryKey = 'user:123'; // Custom primary key format
public $incrementing = false;
public function getKey()
{
return $this->primaryKey;
}
public static function find($key)
{
$location = new RiakLocation(
new RiakNamespace('user', 'profiles'),
$key
);
$fetch = \Riak\Client\Command\Kv\FetchValue::builder($location)
->withNotFoundOk(true)
->build();
$result = app('riak.client')->execute($fetch);
return $result->getValue() ? json_decode($result->getValue(), true) : null;
}
public function save(array $options = [])
{
$location = new RiakLocation(
new RiakNamespace('user', 'profiles'),
$this->getKey()
);
$object = new \Riak\Client\Core\Query\RiakObject();
$object->setValue(json_encode($this->attributes));
$object->setContentType('application/json');
$store = \Riak\Client\Command\Kv\StoreValue::builder($location, $object)
->withW(2)
->build();
app('riak.client')->execute($store);
return true;
}
}
Illuminate\Contracts\Cache\Store:
namespace App\Cache;
use Illuminate\Contracts\Cache\Store;
use Riak\Client\Core\Query\RiakNamespace;
use Riak\Client\Core\Query\RiakLocation;
class RiakCache implements Store
{
protected $client;
public function __construct($client)
{
$this->client = $client;
}
public function get($key, $default = null)
{
$location = new RiakLocation(
new RiakNamespace('cache', 'laravel'),
$key
);
$fetch = \Riak\Client\Command\Kv\FetchValue::builder($location)
->withNotFoundOk(true)
->build();
$result = $this->client->execute($fetch);
return $result->getValue() ? json_decode($result->getValue(), true) : $default;
}
public function put($key, $value, $seconds = null)
{
$location = new RiakLocation(
new RiakNamespace('cache', 'laravel'),
$key
);
$object = new \Riak\Client\Core\Query\RiakObject();
$object->setValue(json_encode($value));
$object
How can I help you explore Laravel packages today?