cristal/php-api-wrapper
cristal/php-api-wrapper is a Laravel/PHP package for building clean, reusable API clients. It offers a fluent interface for requests and responses, supports caching, retries, logging, and testing, and helps keep external API integrations organized and maintainable.
Architecture fit
cristal/php-api-wrapper is an ergonomics layer, not an infrastructure one: it maps remote HTTP resources onto ORM-shaped models and a fluent query builder so developers can write Model::where(...)->get() against a REST API instead of hand-rolling Guzzle calls. That shapes where it fits:
| Scenario | Fit |
|---|---|
| Many third-party APIs with homogeneous read-heavy shapes (list/detail/filter/paginate) | Reasonable — the abstraction pays for itself |
| CRUD-over-REST admin tooling, internal service aggregation | Reasonable |
| One or two integrations | Poor — over-abstraction, more package than problem |
| GraphQL, streaming, webhooks-as-primary, mTLS/HMAC/OAuth2-with-refresh flows | Poor — auth and transport are the value, and the package does not own them |
| Latency-sensitive or high-QPS paths | Poor — the ORM surface hides network I/O and encourages implicit request fan-out |
The Eloquent/Doctrine analogy is the selling point and the core risk: Eloquent's mental model assumes I/O that is local, fast, transactional, and consistent. None of those hold over HTTP. Every place the abstraction feels like the ORM is a place a developer will accidentally issue N sequential requests, assume atomicity that doesn't exist, or treat a 429 as a validation error.
Integration feasibility
Mechanically low-friction: MIT, Composer-installable, Laravel service-provider/config convention. The friction is evidentiary, not mechanical. With zero dependents and a last release of 2023-04-28, there is no production corpus to lean on, no downstream projects absorbing framework-upgrade breakage ahead of us, and no community-validated failure modes. We would be the first meaningful adopter, which means we validate the PHP/Laravel compatibility matrix ourselves.
Technical risk
Key questions to answer before any commitment
Stack fit
Laravel-native, Guzzle-backed by inference. It belongs in the infrastructure/adapter layer only. The honest comparison is Saloon, which is actively maintained, Laravel-first, connector/request-oriented, and has a mature testing story. Saloon trades the Eloquent illusion for explicit request objects — more boilerplate, far less magic, and a maintenance posture we can plan around. If our developers' velocity problem is genuinely "too much HTTP boilerplate across many similar APIs," this package addresses it; if the problem is "our integrations are inconsistent and hard to test," Saloon or our own thin base connector addresses it better.
Migration path
Do not migrate anything. Introduce alongside existing clients behind an internal contract:
ApiClient/repository interfaces first. No package types escape the adapter.Compatibility
Pin exactly in composer.json; verify against the lockfile before the spike, not after. Check for a stale/abandoned flag and the transitive dependency graph. Confirm the Guzzle major version aligns with what the rest of the app already resolves — dual Guzzle majors in one application is a needless conflict class.
Sequencing
Two-week, timeboxed spike with a hard go/no-go gate. Gate criteria: installs clean on current framework; fakes work in tests; error semantics are explicit and typed; a forced failure is diagnosable in under 15 minutes by someone who did not write the integration. If any of those fail, we stop and standardize on Saloon. If all pass, adopt for read-heavy third-party aggregation only, with the adapter boundary mandatory and an explicit note in the architecture decision record that we accept fork responsibility.
Maintenance
Assume we will own this code within 12 months. Plan for a vendored fork or an internal wrapper that pins the package and absorbs patches. The real cost is not bug fixes — it is the framework upgrade treadmill: when Laravel 12/13 lands, an unmaintained HTTP abstraction either blocks us or forces an unplanned fork. Budget a named owner and a quarterly "is upstream still alive?" check; if there are no commits for two consecutive quarters, treat it as internal code.
Support
No vendor, no SLA, no security advisory feed. Support is an internal subject-matter expert — a bus factor of one unless we deliberately spread understanding. Onboarding documentation must cover the abstraction's failure modes explicitly, because the Eloquent surface invites false confidence.
Scaling
The package itself is not the bottleneck; the network is. Throughput comes from our concurrency strategy — queues, connection pooling, batched endpoints — not from the wrapper. Two scaling hazards to design around up front: implicit request fan-out from lazy traversal, and the absence (or misuse) of a shared cache layer. Instrument per-integration request counts and p95 latency from day one; without that, the abstraction will hide exactly the numbers we need.
Failure modes
Ramp-up
Learning curve is inverted from what the API suggests. Day-one productivity is high — developers who know Eloquent are productive in an hour. Debugging competence is the hard part: understanding what SQL-shaped code actually does over the wire requires reading package source, which nobody does until an incident. Mitigate with a short internal guide, a mandated adapter boundary so the surface area stays small, and a rule that any integration touching credentials or money uses an explicit client, not the wrapper.
How can I help you explore Laravel packages today?