friendsofphp/consul-php-sdk
PHP SDK for HashiCorp Consul by FriendsOfPHP. Provides a clean API client to interact with Consul’s HTTP endpoints—service discovery, KV store, health checks, sessions, ACL, and agent/catalog operations—usable in any PHP app or framework.
Installation:
composer require friendsofphp/consul-php-sdk
Verify the package loads in config/consul.php (auto-generated by the package).
First Use Case: Service Discovery
use FriendsOfPHP\Consul\Consul;
$consul = new Consul('http://consul-server:8500');
$services = $consul->getService('web')->get();
getAgent() for local node info (e.g., getAgent()->getSelf()).Configuration:
config/consul.php:
'servers' => [
'default' => [
'host' => env('CONSUL_HOST', 'localhost'),
'port' => env('CONSUL_PORT', 8500),
'scheme' => 'http',
],
],
ConsulFactory for dependency injection:
$consul = app('consul');
$consul->getService('api')->setChecks([
new \FriendsOfPHP\Consul\Checks\ServiceCheck(
'API HTTP Check',
'http',
'/health',
5,
'10s'
)
])->save();
AppServiceProvider boot):
register_shutdown_function(function () {
app('consul')->getService('api')->delete();
});
$consul->getKv()->set('app/config', json_encode(['debug' => true]));
$config = json_decode($consul->getKv()->get('app/config')->getValue(), true);
$consul->getKv()->watch('app/config', function ($event) {
$this->reloadConfig($event->getValue());
});
$session = $consul->getSession()->create('worker-leader', '10s');
$leader = $consul->getSession()->getLeader('worker-leader');
Cache::remember('consul-services', now()->addHour(), function () {
return app('consul')->getAgent()->getServices();
});
Extend the package with a provider:
class ConsulServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('consul', function () {
return new Consul(config('consul.servers.default'));
});
}
public function boot()
{
$this->publishes([
__DIR__.'/config/consul.php' => config_path('consul.php'),
], 'consul-config');
}
}
Expose Consul data via Laravel routes:
Route::get('/services', function () {
return response()->json(app('consul')->getAgent()->getServices());
});
Mock Consul in tests:
$mockConsul = Mockery::mock('overload:consul');
$mockConsul->shouldReceive('getService')->andReturnSelf();
$mockConsul->shouldReceive('get')->andReturn(['web' => ['ServiceAddress' => '127.0.0.1']]);
Connection Timeouts:
$consul = new Consul('http://consul-server:8500', [
'timeout' => 30,
]);
ACL Token Management:
$consul = new Consul('http://consul-server:8500', [
'token' => env('CONSUL_ACL_TOKEN'),
]);
Race Conditions in Sessions:
renew() in long-running processes:
$session = $consul->getSession()->create('lock', '30s');
while (true) {
try {
$session->renew();
break;
} catch (\FriendsOfPHP\Consul\Exception\ConsulException $e) {
sleep(1);
}
}
KV Watching:
setIndex() to resume from a known state:
$consul->getKv()->watch('app/config', $callback, $index);
Service Deregistration:
finally block or Laravel’s terminating event:
app()->terminating(function () {
app('consul')->getService('api')->delete();
});
Enable HTTP Logging:
$consul = new Consul('http://consul-server:8500', [
'http_client' => new \GuzzleHttp\Client([
'debug' => fopen('consul.log', 'w'),
]),
]);
Check HTTP Status Codes:
try-catch to inspect ConsulException:
try {
$consul->getService('nonexistent')->get();
} catch (\FriendsOfPHP\Consul\Exception\ConsulException $e) {
\Log::error($e->getResponse()->getStatusCode());
}
Validate Consul Server Health:
$response = $consul->getAgent()->getSelf();
if (!$response->getStatus()) {
throw new \RuntimeException('Consul server unreachable');
}
Custom HTTP Client:
$client = new \GuzzleHttp\Client(['timeout' => 10]);
$consul = new Consul('http://consul-server:8500', ['http_client' => $client]);
Event Dispatching:
$consul->getKv()->watch('app/config', function ($event) {
event(new ConfigUpdated($event->getValue()));
});
Retry Logic:
$attempts = 0;
while ($attempts < 3) {
try {
$consul->getService('api')->get();
break;
} catch (\Exception $e) {
$attempts++;
sleep(2 ** $attempts);
}
}
Local Development:
docker-compose with Consul:
services:
consul:
image: consul:latest
ports:
- "8500:8500"
http://localhost:8500.How can I help you explore Laravel packages today?