Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rest Client Sdk Bundle Laravel Package

mapado/rest-client-sdk-bundle

Symfony bundle that integrates the Mapado REST Client SDK, registering API client services and configuration in the container so Symfony apps can inject and use Mapado REST clients with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Read the architecture before you type composer require.

This is a Symfony bundle, not a Laravel package. It has no extra.laravel.providers, no service-provider auto-discovery, and it boots from a Symfony Kernel, not Laravel's container. Dropping it into a Laravel app will install fine and then do nothing useful — it will never register itself, and shimming Symfony's DI/kernel to force it to boot is not a path you want to own. The honest starting point is: you adopt mapado/rest-client-sdk, not the bundle. The bundle is ~100 lines of config/DI glue you will rewrite idiomatically in Laravel.

composer require mapado/rest-client-sdk

2. Look here first, in this order.

  • The underlying SDK's Client, EntityManager, and SdkClientRegistry classes — these are the actual API you'll use day-to-day.
  • The SDK's JSON descriptor format / mapping config — this is the only genuinely novel surface. Everything else is familiar Guzzle + serialization.
  • The bundle's DependencyInjection/Configuration.php and Resources/config/services.xml on GitHub — not to install them, but as a reference for how the maintainer expects clients to be wired. Mirror that shape in your own config so a future swap (or a Symfony service in a shared package) is mechanical.

3. Wire it in a service provider.

Create config/rest_clients.php (or hang it off config/services.php) with the same declarative shape the bundle uses — named clients, base URI, entity→endpoint mapping:

// config/rest_clients.php
return [
    'acme' => [
        'base_url' => env('ACME_API_URL'),
        'mapping'  => [
            App\Generated\Acme\Invoice::class  => '/invoices',
            App\Generated\Acme\Customer::class => '/customers',
        ],
    ],
];

Then a provider binds the SDK's client singleton per named client, keyed through your own abstraction:

final class RestClientServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(AcmeGateway::class, function ($app) {
            $client = new Client(
                new Psr18Client(/* Guzzle or Symfony HttpClient PSR-18 adapter */),
                /* serializer */,
            );

            return new AcmeGateway($client);
        });
    }
}

4. First use case: read-only hydration of one resource.

Prove the whole pipeline with the least ambitious call — fetch one entity by ID and get a typed object back:

final class InvoiceController
{
    public function __construct(private AcmeGateway $acme) {}

    public function show(int $id): JsonResponse
    {
        return response()->json($this->acme->invoices()->find($id));
    }
}

If that works, collections, relations, and writes are all variations. If it fails, the bug is almost always the entity mapping or the serializer config, not the HTTP transport — debug there first.

Implementation Patterns

Wrap the SDK behind a hand-written gateway, always. Call sites should depend on your interface, never on map ado\RestClientSdk\* types. This is the single highest-leverage decision you'll make, because it's what lets you swap the client layer (to Symfony HttpClient, to a Jane PHP generated client, to a maintained fork) without touching controllers or jobs. It also keeps SDK DTOs out of your HTTP responses and queue payloads.

Generate clients at build time, not runtime. The SDK's strength is typed DTOs generated from the vendor's JSON descriptor. Run the generator in CI, emit into a dedicated namespace (App\Generated\VendorApi), and commit the output so it surfaces as a reviewable diff. Never generate on boot — that's a per-request metadata parse you don't want in production. Treat the generated directory as read-only and enforce that with a lint rule or CI check.

Repository-per-resource, not a fluent query builder. The ergonomic API is $client->getRepository(Invoice::class)->find($id) plus the collection methods it exposes. When the target API has filtering/sorting the repository doesn't model, drop to the raw PSR-18 client for that endpoint and map the result yourself. Bolting a fluent query DSL on top is how these integrations rot.

Plain PHP DTOs, no base class. The hydrator writes into whatever class you map. Keep them as simple objects with typed properties and setters. Don't extend a Laravel model or a framework entity base — it buys nothing and couples your generated code to the app.

One client per API, one auth concern per client. Registration, retries, and logging are cross-cutting conventions. Put them in the gateway or in a Guzzle middleware stack so all calls to acme behave identically. This is the "one client pattern" payoff — a new endpoint becomes a config/mapping change, not a new HTTP wrapper.

Testing seam: fake at the PSR-18 layer. Bind a MockClient/in-memory transport in a test service provider and assert on the DTOs your gateway returns. Do not mock the SDK's Client — you'd be testing your own mocks. A functional test that fakes the transport and exercises real hydration is worth ten unit tests with stubbed internals.

Config mirrors the bundle's shape. Keep your config keys (base_url, mapping, named clients) close to the bundle's Configuration.php so the mental model transfers, and so that if you ever move to Symfony, or the bundle is revived, migration is mechanical rather than a rewrite.

Gotchas and Tips

Package discovery will silently do nothing. composer require mapado/rest-client-sdk-bundle in Laravel installs the bundle and then never boots it. You'll get confused "service not found" errors or, worse, no error at all because nothing is trying to use it. Either don't install the bundle, or if you must for some shared package, don't expect Symfony semantics — engineers who see the word "Bundle" will assume auto-wiring that doesn't exist here.

Abandonment is the dominant risk, not code quality. Four stars, zero dependents, single maintainer, no visible security process. Expect to own this code on day one. Pin the version, vendor or fork it if it goes to production, and budget a named maintainer plus a quarterly audit. The dependency is thin enough that forking is realistic — treat that as your fallback, not your disaster scenario.

Composer constraints will fight you. The bundle and its ancestors target older Symfony (3.x/4.x), JMS Serializer, and Guzzle. On PHP 8.2+/Laravel 10–11, expect resolution conflicts and to loosen constraints or vendor a patched fork. Verify the SDK's PHP/Guzzle/Serializer constraints before you commit to a spike, not after.

Mapping errors masquerade as transport errors. A wrong entity→endpoint mapping, a missing @id field, or a serializer group mismatch all surface as "couldn't hydrate" from deep inside the client. When a call fails, reproduce with the raw PSR-18 client first — if the HTTP response is fine, the bug is mapping/serialization, not networking.

Schema drift is silent. The vendor adds or renames a field and your generated client keeps working while quietly mis-populating DTOs. Mitigate with contract tests run against a sandbox on a schedule, not just at deploy. Treat the vendor's descriptor as a stable contract you're testing against, and fail loudly on unexpected fields if the API warrants strictness.

Retries, timeouts, and backoff are not provided. The client is Guzzle/PSR-18 based and stateless. Add explicit timeout and retry middleware in the gateway, per client, with backoff. Without this, a degraded vendor becomes cascading latency in your own workers. This is the most common production failure for this pattern.

Cache any boot-time metadata. If you register entity mappings or parse descriptors on every request, cache them (config cache / a compiled PHP array). It's a per-request cost that doesn't show up in a spike and hurts at scale.

Watch deserialization on large payloads. Per-request hydration cost is real on big collections. If you're pulling thousands of rows, page on the API side rather than hydrating everything, and measure before you assume it's free.

Keep an abstraction seam from day one. The most likely long-term failure is an abandoned dependency blocking a PHP or Laravel upgrade. A gateway interface with a small number of methods is cheap insurance — when the SDK stops resolving, you replace one class's internals and call sites keep working. Time-box the spike, pin the version, and document the fork point in the README so the next engineer knows what they're inheriting.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource