2017 © Pedro Peláez
 

library rest-client-sdk

Rest Client SDK for hydra API

image

mapado/rest-client-sdk

Rest Client SDK for hydra API

  • Tuesday, July 17, 2018
  • by jdeniau
  • Repository
  • 13 Watchers
  • 9 Stars
  • 4,604 Installations
  • PHP
  • 2 Dependents
  • 0 Suggesters
  • 3 Forks
  • 9 Open issues
  • 68 Versions
  • 6 % Grown

The README.md

Rest Client Sdk StyleCI Scrutinizer

PHP Rest Client SDK for JSON API., (*1)

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., (*2)

installation

composer require mapado/rest-client-sdk

Usage

Imagine you have those API endpoints:, (*3)

  • /v2/carts
  • /v2/carts/{id}
  • /v2/cart_items
  • /v2/cart_items/{id}

You will need to have two entities, let's say:, (*4)

  • Foo\Bar\Model\Cart
  • Foo\Bar\Model\CartItem

You will need to declare one Mapping containing your two ClassMetadata, (*5)

Entity declarations

Configure an entity

Imagine the following entities:, (*6)

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

Entity definitions:, (*7)

  • key must be the key of your API endpoint

Attributes definition:, (*8)

  • name the name of the key in the API return format
  • type type of the attribute

Relations definition:, (*9)

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

UnitOfWork

EntityRepository 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., (*10)

Configuration

Using Symfony ?

There is a bundle to easily integrate this component: mapado/rest-client-sdk-bundle., (*11)

Once configured, you can get a client like this:, (*12)

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

Not using Symfony

You need to configure client this way:, (*13)

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

use Mapado\RestClientSdk\SdkClientRegistry;

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

It can be easier to manager multiple clients. You can then call:, (*14)

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

// or

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

Accessing data

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 <Name>)
$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

$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, (*15)

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., (*16)

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., (*17)

Custom serialization

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

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

to do so, you can specify a $serializationContext in the persist and update method:, (*20)

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

Extending the repository

If you need to extend the EntityRepository, you can just do something like that:, (*21)

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:, (*22)

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

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

You can see all the exceptions in this folder., (*24)

If you need to access the body of the response from your API you can do something like this:, (*25)

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

rest-client-sdk does work well with PHPStan. See the related documentation., (*26)

Hacking

This library is tested on multiple Symfony and PHP version thanks to composer-test-scenarios., (*27)

But there is a conflict between ocramius/proxy-manager, composer 1&2, and php version., (*28)

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

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 but it requires composer 2 absolutely, and we (Mapado) are not ready for this., (*30)

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

The Versions

22/09 2017
06/07 2017

dev-jp-fix-unit-of-work-no-store

dev-jp-fix-unit-of-work-no-store

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

02/05 2016
15/03 2016

v0.9.0

0.9.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

11/03 2016

v0.8.3

0.8.3.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

07/03 2016

v0.8.2

0.8.2.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

07/03 2016

v0.8.1

0.8.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

01/03 2016

v0.8.0

0.8.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

05/02 2016

v0.7.0

0.7.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

22/01 2016

v0.6.1

0.6.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

22/01 2016

v0.6.0

0.6.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

21/01 2016

v0.5.1

0.5.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

18/01 2016

v0.5.0

0.5.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

05/01 2016

v0.4.4

0.4.4.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

23/12 2015

v0.4.3

0.4.3.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

07/12 2015

v0.4.2

0.4.2.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

03/12 2015

v0.4.1

0.4.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

05/11 2015

v0.4.0

0.4.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

26/10 2015

v0.3.1

0.3.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

23/10 2015

v0.3.0

0.3.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

15/10 2015

v0.2.1

0.2.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

13/10 2015

v0.2.0

0.2.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

08/10 2015

v0.1.2

0.1.2.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

08/10 2015

v0.1.1

0.1.1.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet

08/10 2015

v0.1.0

0.1.0.0

Rest Client SDK for hydra API

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dimitri Allegoet