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 Laravel Package

mapado/rest-client-sdk

A PHP toolkit for building REST API client SDKs. mapado/rest-client-sdk provides a structured base for wrapping HTTP endpoints, handling requests, responses, and serialization so you can expose a clean, reusable client API around any REST service.

Deep Wiki
Context7

Getting Started

The SDK is a thin consumer for Hydra / JSON-LD APIs (the hypermedia format used by API Platform and Hydra-enabled Symfony apps). It does not generate code or a server; it discovers an API from its hydra:entrypoint, then hydrates responses into your own PHP entity classes.

1. Install

composer require mapado/rest-client-sdk guzzlehttp/guzzle

You also need PSR-18/PSR-7 support (Guzzle covers both) and, in practice, you will be adding mapado/hydra-api-hydrator entities/mappings yourself.

2. Point it at the entrypoint

The first thing to do is curl (or open in a browser) the API's entrypoint, usually /api or /api/docs.jsonld. Confirm you see @context, @id, @type, and a list of hydra:supportedClass / hydra:entrypoint. If that document is wrong, the SDK is wrong — the SDK trusts it completely.

3. Wire a client

use GuzzleHttp\Client as GuzzleClient;
use Mapado\RestClientSdk\SdkClient;

$mapping = [
    'Member' => [
        'class'      => App\Entity\Member::class,
        'repository' => App\Repository\MemberRepository::class,
    ],
    'Post' => [
        'class' => App\Entity\Post::class,
    ],
];

$sdk = new SdkClient(
    new GuzzleClient(['base_uri' => 'https://api.example.com/']),
    'https://api.example.com/api',   // Hydra entrypoint
    $mapping
);

$members = $sdk->getRepository('Member')->findAll();

4. First use case

The canonical "hello world" is: annotate one entity with its Hydra attributes and identifier, register it in the mapping, and call findAll() on its repository. Once that hydrates into real objects, everything else (relations, filtering, pagination) is incremental.

Where to look first: the package README for the exact annotation namespace (@Attribute, @Identifier, @OneToMany, @ManyToOne), the SdkClient constructor signature for your pinned version, and the API's own JSON-LD docs. The package is small; reading SdkClient and RestClient end-to-end takes 20 minutes and answers most questions faster than the docs.

Implementation Patterns

Repository per resource. $sdk->getRepository('Member') returns an object exposing find, findAll, findBy, and typically findOneBy. Treat it exactly like a Doctrine repository — controller/service code should depend on a repository interface, not on SdkClient, so you can swap the transport later.

Custom repositories. Register a repository class in the mapping and extend the SDK's base repository to add domain queries:

class MemberRepository extends \Mapado\RestClientSdk\Repository\AbstractRepository
{
    public function findActive(): array
    {
        return $this->findBy(['active' => true]);
    }
}

This is the main extension point and the cleanest way to keep query-parameter conventions out of your controllers.

Filtering, sorting, pagination via query params. Hydra collections generally expose page, itemsPerPage, and property filters. Pass them through the repository's findBy:

$page = $sdk->getRepository('Member')->findBy(
    ['country' => 'FR'],
    ['createdAt' => 'desc'],
    30,
    2   // page 2
);

Inspect the response's hydra:view / hydra:member keys when pagination behaves unexpectedly — some servers use hydra:first/next/last, others don't.

Relations are IRIs, resolve lazily. A @ManyToOne property arrives as a string IRI (/api/members/42), not an embedded object. Your entity holds the IRI; the repository dereferences it. Do not eagerly walk relations in a loop over 500 items — that's N+1 over HTTP and it will be slow and rate-limited.

Auth via Guzzle middleware. Don't subclass the client; push a handler:

$stack = HandlerStack::create();
$stack->push(Middleware::mapRequest(fn ($r) =>
    $r->withHeader('Authorization', 'Bearer ' . $token)
));
$sdk = new SdkClient(new GuzzleClient(['handler' => $stack, 'base_uri' => $base]), $entrypoint, $mapping);

Caching the API documentation. The SDK needs the Hydra documentation to know which properties and types exist. In production, warm and cache that document (PSR-6/PSR-16) rather than re-fetching on every process boot — with PHP-FPM you may be paying for it per request. Look for the hydra client's cache option in your version.

Testing. Inject a Guzzle client backed by MockHandler returning canned JSON-LD fixtures. This is the only sane way to test entity hydration, pagination edge cases, and error paths without a live server. Keep at least one fixture per resource.

Layering. In a real application: Controller → Service → Repository (SDK) → Guzzle → API. The SDK types should not leak into your domain. If your project has both a local DB and a remote Hydra service, keep the two persistence paths clearly separated behind interfaces.

Gotchas and Tips

The Hydra document is the contract — and it lies. Wrong @type (e.g. string vs integer), missing hydra:supportedProperty, or an entity not listed under hydra:supportedClass produces silent null fields, not exceptions. When a property "doesn't hydrate," debug the JSON-LD first, the PHP mapping second.

@id (IRI) is not your id. The hydrator stores the full IRI (or path) separately from a numeric identifier. Code that compares $entity->getId() to a raw @id will fail. Normalize early: extract the trailing ID once on hydration.

Absolute vs relative IRIs. APIs behind a reverse proxy commonly emit relative IRIs (/api/members/42). If the SDK client's base_uri doesn't match, resolution breaks with 404s that look like routing bugs. Pin base_uri to the same host scheme the doc uses.

Circular references. A Member with a posts collection of Post objects that each reference Member can blow up during hydration or serialization. Keep one direction lazily unresolved and avoid deep graph traversal in response objects.

Empty collections are not errors. hydra:member: [] sometimes hydrates to null depending on version and mapping. Guard with ?? [] in consumers, or add a repository normalizer.

Errors are also Hydra. A 4xx/5xx may return a hydra:Error body. Catch the SDK's exception type, then inspect hydra:description — the raw status code alone usually isn't enough for logging or user messaging.

Debugging. Add Guzzle's Middleware::history($container) and dump request/response pairs. Most "SDK bugs" are wrong query parameter names or a mapping typo, and seeing the outgoing URL resolves it in one look.

Low maintenance surface. This package is niche and thinly maintained (small star count, infrequent releases). Pin the exact version in composer.json, commit the lock file, and avoid depending on undocumented internals like hydrator class names. If the API you consume is API Platform, evaluate calling its JSON-LD endpoints with a plain typed HTTP client — you lose convenience but gain a supportable dependency.

Extension points worth knowing: custom repository classes, custom mapping entries (class + repository per resource), and swapping the HTTP client/middleware. The hydrator itself is a separate package; type conversion quirks (dates, floats, booleans from strings) are fixed there, not here — check both repos when a cast goes wrong.

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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core