PHPackages                             mapado/rest-client-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. mapado/rest-client-sdk

ActiveLibrary[API Development](/categories/api)

mapado/rest-client-sdk
======================

Rest Client SDK for hydra API

v3.0.0(1mo ago)1125.9k↓25%3[5 PRs](https://github.com/mapado/rest-client-sdk/pulls)2MITPHPPHP ^8.4CI passing

Since Oct 8Pushed 1mo ago11 watchersCompare

[ Source](https://github.com/mapado/rest-client-sdk)[ Packagist](https://packagist.org/packages/mapado/rest-client-sdk)[ RSS](/packages/mapado-rest-client-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (29)Versions (101)Used By (2)

Rest Client Sdk [![StyleCI](https://camo.githubusercontent.com/0172cdcc10ae8029c764cf55dc19ee9b142c121f88d2849d8fe474ec4ab7a00b/68747470733a2f2f7374796c6563692e696f2f7265706f732f34333535333133362f736869656c64)](https://styleci.io/repos/43553136) [![Scrutinizer](https://camo.githubusercontent.com/daf1d26fb7d203eb26acff3acdbdf5e54c8f1ef1c77e9907547252f9c46979ed/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d617061646f2f726573742d636c69656e742d73646b2f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mapado/rest-client-sdk/)
============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#rest-client-sdk--)

PHP Rest Client SDK for JSON API.

This client tries to avoid the complexity of implementing a custom SDK for every API you have. You just have to implements your model and a little configuration and it will hide the complexity for you.

installation
------------

[](#installation)

```
composer require mapado/rest-client-sdk
```

Usage
-----

[](#usage)

Imagine you have those API endpoints:

- /v2/carts
- /v2/carts/{id}
- /v2/cart\_items
- /v2/cart\_items/{id}

You will need to have two entities, let's say:

- Foo\\Bar\\Model\\Cart
- Foo\\Bar\\Model\\CartItem

You will need to declare one `Mapping` containing your two `ClassMetadata`

Entity declarations
-------------------

[](#entity-declarations)

### Configure an entity

[](#configure-an-entity)

Imagine the following entities:

```
namespace Acme\Foo\Bar;

use Mapado\RestClientSdk\Mapping\Attributes as Rest;

#[Rest\Entity(key: "carts")]
class Cart
{
   #[Rest\Id, Rest\Attribute(name: "@id", type: "string")]
  private $iri;

   #[Rest\Attribute(name: "status", type: "string")]
  private $status;

  #[Rest\Attribute(name: "created_at", type: "datetime")]
  private $createdAt;

  #[Rest\OneToMany(name: "cart_items", targetEntity: "CartItem")]
  private $cartItemList;

  // getters & setters ...
}

/**
 * @Rest\Entity(key="cart_items")
 */
#[Rest\Entity(key: "cart_items")]
class CartItem
{
  #[Rest\Id, Rest\Attribute(name: "@id", type: "string")]
  private $iri;

  #[Rest\Attribute(name: "number", type: "integer")]
  private $number;

  #[Rest\ManyToOne(name: "cart", targetEntity: "Cart")]
  private $cart;
}
```

### Explanations

[](#explanations)

`Entity` definitions:

- `key` must be the key of your API endpoint

Attributes definition:

- `name` the name of the key in the API return format
- `type` type of the attribute

Relations definition:

- `name` the name of the key in the API return format
- `targetEntity` class name of the target entity

### UnitOfWork

[](#unitofwork)

[EntityRepository](https://github.com/mapado/rest-client-sdk/blob/master/src/EntityRepository.php) has a UnitofWork used for PUT and POST requests. It sends only changed data not the full model by comparing with the entity stored on GET request.

Configuration
-------------

[](#configuration)

### Using Symfony ?

[](#using-symfony-)

There is a bundle to easily integrate this component: [mapado/rest-client-sdk-bundle](https://github.com/mapado/rest-client-sdk-bundle).

Once configured, you can get a client like this:

```
$sdkClient = $this->get('mapado.rest_client_sdk.foo');
// or $sdkClient = $this->get('mapado.rest_client_sdk')->getSdkClient('foo');
```

### Not using Symfony

[](#not-using-symfony)

You need to configure client this way:

```
use Mapado\RestClientSdk\Mapping;
use Mapado\RestClientSdk\RestClient;
use Mapado\RestClientSdk\SdkClient;
use Mapado\RestClientSdk\Mapping\Driver\AttributeDriver;

$restClient = new RestClient(
  new GuzzleHttp\Client(),
  'http://path-to-your-api.root'
);

// if you need to pass some headers to the client, you can do something like this:
// $restClient = new RestClient(
//   new GuzzleHttp\Client(['headers' => [ 'Authorization' => 'Bearer foobar' ]]),
//   'http://path-to-your-api.root'
// );
// See guzzle documentation for more informations

$annotationDriver = new AttributeDriver($cachePath, ($debug = true));

$mapping = new Mapping('/v2'); // /v2 is the prefix of your routes
$mapping->setMapping($annotationDriver->loadDirectory($pathToEntityDirectory));

$sdkClient = new SdkClient($restClient, $mapping);
```

#### Optionnal: create a SdkClientRegistry

[](#optionnal-create-a-sdkclientregistry)

```
use Mapado\RestClientSdk\SdkClientRegistry;

$registry = new Registry(['my-api' => $sdkClient]);
```

It can be easier to manager multiple clients. You can then call:

```
$sdkClient = $registry->getSdkClient('my-api');

// or

$sdkClient = $registry->getSdkClientForClass('\App\Entity\SomeEntity');
```

Accessing data
--------------

[](#accessing-data)

### Fetching an entity / a list of entities

[](#fetching-an-entity--a-list-of-entities)

```
$repository = $sdkClient->getRepository('Acme\Foo\Bar\Cart');

// you can also access the repository by model key:
// $repository = $sdkClient->getRepository('cart');

// Find entity based on ID as defined in the entity by @Rest\Id
$cart = $repository->find(1);

// If you need to pass extra query parameters:
$cart = $repository->find(1, ['foo' => 'bar']); // will call /v2/carts/1?foo=bar

// Find all entities in the database
$cart = $repository->findAll();

// Find one entity based on the fielddefined in the function name (in this case )
$cart = $repository->findOneByName('username'); // will call /v2/carts?name=username

// Find one entity based on the criteria defined in the array
$cart = $repository->findOneBy(array(
  'name' => 'username',
  'date' => '1-1-2016',
)); // will call /v2/carts?name=username&date=1-1-2016

// To find all matches for the two examples above replace findOneByName() with findByName() and findOneBy() with findBy()
```

### Creating a new instance

[](#creating-a-new-instance)

```
$cart = new \Acme\Foo\Bar\Cart();
$cart->setStatus('awaiting_payment');
$cart->setCreatedAt(new \DateTime());
$repository->persist($cart);
```

The `persist` operation will send a `POST` request with the serialized object to the API endpoint and return the newly created object

### Updating an instance

[](#updating-an-instance)

```
$cart = $repository->find(13);
$cart->setStatus('payed');
$repository->update($cart);
```

The `update` operation will send a `PUT` request with the serialized object to the API endpoint (using the object `Id`) and return the updated object.

### Deleting an instance

[](#deleting-an-instance)

```
$cart = $repository->find(13);
$repository->remove($cart);
```

The `remove` operation will send a `DELETE` request to the API endpoint using the object Id.

### Custom serialization

[](#custom-serialization)

By default, when serializing, the SDK return only the Id to existing relations (like one-to-many).

You may want to serialize OneToMany relations though (imagine you have a `Cart` and you want to update linked `cartItems`)

to do so, you can specify a `$serializationContext` in the `persist` and `update` method:

```
$repostory->update($cart, ['serializeRelations' => ['cartItems']]);
```

### Extending the repository

[](#extending-the-repository)

If you need to extend the [EntityRepository](https://github.com/mapado/rest-client-sdk/blob/master/src/EntityRepository.php), you can just do something like that:

```
namespace Acme\Foo\Bar\Repository;

use Mapado\RestClientSdk\EntityRepository;

class CartRepository extends EntityRepository
{
  public function findOneByFoo($bar)
  {
    // generate the path to call
    $path = $data = $this->restClient->get($path); // ...
    return $this->sdk->getModelHydrator()->hydrate($data, $this->entityName); // hydrate for an entity, hydrateList for a list
  }
}
```

Update your entity `Rest` attribute to let the entity be aware of it's repository:

```
namespace Acme\Foo\Bar;

use Mapado\RestClientSdk\Mapping\Attributes as Rest;

#[Rest\Entity(key: "carts", repository: Acme\Foo\Bar\Repository\CartRepository::class)]
class Cart {
```

Handling exceptions
-------------------

[](#handling-exceptions)

The SDK will throw an Exception if your API return something different than a 2xx or a 404 status code.

You can see all the exceptions in [this folder](https://github.com/mapado/rest-client-sdk/tree/master/src/Exception).

If you need to access the body of the response from your API you can do something like this:

```
use Mapado\RestClientSdk\Exception\RestClientException;

try {
  // do something that will fail
} catch (\RestClientException $e) {
  $response = $e->getResponse(); // $response should be a Psr\Http\Message\ResponseInterface
  $body = $response->getBody();
  var_dump($body); // will dump your response body
}
```

PHPStan
-------

[](#phpstan)

rest-client-sdk does work well with PHPStan. See [the related documentation](phpstan-extension/README.md).

Hacking
-------

[](#hacking)

This library is tested on multiple Symfony and PHP version thanks to [composer-test-scenarios](https://github.com/g1a/composer-test-scenarios).

But there is a conflict between ocramius/proxy-manager, composer 1&amp;2, and php version.

In order to sort this issue, it may be usefull to update scenarios with this command for scenario with php 7.4:

```
docker run --rm --interactive --tty --volume $PWD:/app -w "/app" roadiz/php74-runner composer scenario:update
```

This should be resolved with [ocramius/proxy-manager#2.9.0](https://packagist.org/packages/ocramius/proxy-manager#2.9.0) but it requires composer 2 absolutely, and we (Mapado) are not ready for this.

The path to fix this is to bump a major version with `"ocramius/proxy-manager": "^2.9.0"` that requires composer^2

###  Health Score

66

—

FairBetter than 99% of packages

Maintenance89

Actively maintained with recent releases

Popularity35

Limited adoption so far

Community28

Small or concentrated contributor base

Maturity97

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 71.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~44 days

Recently: every ~58 days

Total

87

Last Release

53d ago

Major Versions

v0.37.0 → v2.0.02024-07-29

v2.2.1 → v3.0.02026-03-26

PHP version history (6 changes)v0.26.2PHP ^7.0

v0.28.0PHP ^7.1

v0.32.0PHP ^7.2

v0.36.0PHP ^7.2|^8.1

v0.37.0PHP ^8.1

v3.0.0PHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/3277986d0e1f93c7e8a58fdaf1b52e3f5a1588e73dfa298d33aafb1ebbde5ef2?d=identicon)[jdeniau](/maintainers/jdeniau)

![](https://www.gravatar.com/avatar/90d135128b469dc38fcf186ac78d0f2cd82fc696ffcf5be8a8c486b7bd911ff6?d=identicon)[mapado](/maintainers/mapado)

---

Top Contributors

[![jdeniau](https://avatars.githubusercontent.com/u/1398469?v=4)](https://github.com/jdeniau "jdeniau (324 commits)")[![JulienRAVIA](https://avatars.githubusercontent.com/u/8202241?v=4)](https://github.com/JulienRAVIA "JulienRAVIA (58 commits)")[![dallegoet](https://avatars.githubusercontent.com/u/1019982?v=4)](https://github.com/dallegoet "dallegoet (12 commits)")[![Fe4nn0r](https://avatars.githubusercontent.com/u/805171?v=4)](https://github.com/Fe4nn0r "Fe4nn0r (10 commits)")[![bjulien](https://avatars.githubusercontent.com/u/3918730?v=4)](https://github.com/bjulien "bjulien (10 commits)")[![badaz](https://avatars.githubusercontent.com/u/5735255?v=4)](https://github.com/badaz "badaz (9 commits)")[![ambroisemaupate](https://avatars.githubusercontent.com/u/380026?v=4)](https://github.com/ambroisemaupate "ambroisemaupate (7 commits)")[![Nickinthebox](https://avatars.githubusercontent.com/u/2796997?v=4)](https://github.com/Nickinthebox "Nickinthebox (5 commits)")[![celestialaly](https://avatars.githubusercontent.com/u/1677866?v=4)](https://github.com/celestialaly "celestialaly (5 commits)")[![Steit](https://avatars.githubusercontent.com/u/4642644?v=4)](https://github.com/Steit "Steit (4 commits)")[![jmfeurprier](https://avatars.githubusercontent.com/u/8434690?v=4)](https://github.com/jmfeurprier "jmfeurprier (3 commits)")[![didier2l](https://avatars.githubusercontent.com/u/47220517?v=4)](https://github.com/didier2l "didier2l (2 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (2 commits)")[![thomasdiluccio](https://avatars.githubusercontent.com/u/3739767?v=4)](https://github.com/thomasdiluccio "thomasdiluccio (2 commits)")[![leroy0211](https://avatars.githubusercontent.com/u/2051658?v=4)](https://github.com/leroy0211 "leroy0211 (1 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

client-sdkhydra-apiphprest-apisdk

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mapado-rest-client-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/mapado-rest-client-sdk/health.svg)](https://phpackages.com/packages/mapado-rest-client-sdk)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[statamic/cms

The Statamic CMS Core Package

4.8k3.2M720](/packages/statamic-cms)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
