friendsofphp/consul-php-sdk
A thin PHP wrapper around the Consul HTTP API, covering agent, catalog, health, kv, session, and txn services. It returns ConsulResponse objects, throws typed exceptions, and includes helpers for locks and semaphores.
Architecture fit
agent, catalog, health, kv, session, txn, plus the full surface added in 5.4: ACL, Config, Connect, Coordinate, DiscoveryChain, Event, Operator, Peering, PreparedQuery, Snapshot, Status).onOneServer depends on a shared cache, and Consul sessions are a legitimate alternative if Consul is already the platform bet); KV for runtime config/feature flags; Snapshot + Operator for DR and cluster-health tooling that previously lived only in Go/Terraform workflows.Integration feasibility
symfony/http-client pin if that component is already a direct or transitive dependency.new Consul\Services\KV()), but that is also the trap: without a binding, you get new KV() scattered across the codebase with hardcoded addresses and no token handling. The binding is the actual scoping item, and it is small but mandatory (~3–5 engineering days including tests).symfony/http-client's MockHttpClient makes unit-level stubbing viable, and a Consul container in CI covers contract behavior. Budget for it — there is no hosted sandbox.Technical risk
composer update.ClientException, 5xx → ServerException, but transport/TLS/DNS failures surface as Symfony TransportExceptionInterface. Code that only catches the SDK's exceptions will 500 on an agent outage.Key questions
onOneServer sufficient for locking and config? Decide the platform bet before the SDK bet — this package is downstream of that decision.localhost:8500 default) or remote server addressing from every app node?CONSUL_HTTP_TOKEN env (SDK-native, aligns with container/CI conventions) or a secrets manager? If env, does that meet our secret-handling standard, and what is the rotation runbook? A rotated token that misses one service produces a ClientException that looks like an outage.Stack fit
Http facade. Frame it as isolation, not duplication — Consul timeouts, pooling, and circuit breaking stay independent of application HTTP traffic. Flag it in the dependency footprint review so nobody "consolidates" it later.psr/log 2/3 aligns with Monolog 3 in Laravel 10+. Bridge the existing PSR logger so SDK logs land in the app's normal channels.Migration path
curl/Guzzle calls to Consul, or a fork of the pre-5.0 package. A fork is a genuine migration: namespace change (SensioLabs\Consul → Consul), typed request bodies (arrays now, not strings), removed factory and most interfaces. Scope it explicitly; it is not a composer require.Compatibility
composer why-not friendsofphp/consul-php-sdk 5.4 against the real lockfile before committing. Highest-probability conflicts: a pinned symfony/http-client, psr/log 1.x transitives, and PHP 8.1 CI runners.^5.4 with an explicit upgrade policy and a CI gate on the lockfile diff.Sequencing
ConsulServiceProvider, config/consul.php (scheme, host, port, token, timeouts, DC), singleton ClientInterface + per-service bindings, facade, a Consul health check surfaced to ops, PSR logger bridge, and a retry/circuit-breaker wrapper — the SDK has none.Connect intentions, Peering, Snapshot + Operator for DR and cluster reporting.Sequencing rule: phases 3 and 4 must not share a release. Locking changes correctness semantics; it needs its own rollback story.
Maintenance
Support
Http::withToken()->put(...) while you wait. That keeps worst-case severity low. Document that escape hatch.Scaling
localhost:8500 default. This is the design the SDK assumes and it prevents every app node from hammering the server cluster directly.wait window. M concurrent watchers = M workers permanently occupied. Cap concurrency, run watchers as long-lived Horizon/queue workers, or prime a cache in the background and read the cache in the request path.Failure modes
TransportExceptionInterface, not an SDK exception. Unhandled, it is a hard 500 on every request path that touches Consul. Never call Consul synchronously in a hot path without a timeout and a cached fallback.ClientException): most often ACL token misconfiguration or a missed rotation. Alert on it distinctly from generic errors — it is a config bug, not an outage, and the remediation is different.ServerException): typically leader election. Transient; retry-with-backoff is your code.stale/consistent are first-class options, choose per call site deliberately rather than accepting the default.Ramp-up
ConsulResponse return, typed exceptions). The real learning curve is Consul itself: ACLs, sessions, blocking queries, consistency modes, agent-vs-server topology. Budget 2–3 engineers for Consul literacy, not SDK training.How can I help you explore Laravel packages today?