phpCE, 27. října 2018, Praha
Asi jste v poslední době slyšeli o GraphQL. Je tedy opravdu čas opustit REST API, jak někteří tvrdí? Myslím, že zdaleka ne - a chtěl bych vám ukázat existující alternativu pro vytváření dobrých REST API - standard JSON API, okolo kterého se rozvíjí zajímavý ekosystém i v PHP.
1 of 37
Download to read offline
More Related Content
JSON API: Možná nepotřebujete GraphQL
1. … možná nepotřebujete GraphQL
phpCE, 27. října 2018
Ondřej Machulda
@OndraM
Anotovaná verze slajdů
3. GraphQL
Zdroj: Jeremykemp at English Wikipedia, https://commons.wikimedia.org/wiki/File:Gartner_Hype_Cycle.svg
Spíše jde o klasický hype cyklus, kterým si
projde většina technologií.
Prošel si jím i konec konců REST.
5. RPC? REST? GraphQL?
Alternativ je přitom více. Narozdíl od RPC a RESTu, což jsou obecné koncepty,
je GraphQL konkrétní specifická implementace API. Ale to taky znamená, že je
vhodné pro specifické použití.
6. Zdroj: Phil Sturgeon, https://philsturgeon.uk/2018/05/21/picking-an-api-paradigm-implementation/
Přednáška o různých API paradigmatech:
Nate Barbettini – API Throwdown: RPC vs REST vs GraphQL
https://www.youtube.com/watch?v=IvsANO0qZEg
Phil Sturgeon – Picking the right API Paradigm
philsturgeon.uk/2018/05/21/picking-an-api-paradigm-implementation/
Je třeba znát tradeoffy různých typů API. Navíc
každý projekt má jiné potřeby a požadavky.
Ale pro značnou situací, které jako PHP vývojáři
řešíme, pro nás bude výhodnější REST API.
7. Zdroj: Ali Emirov, https://www.flickr.com/photos/27435717@N00/44545597592/, CC BY-NC 2.0Zdroj: https://www.pexels.com/photo/blur-breakfast-chef-cooking-262978/
REST GraphQLaurace
Phil Sturgeon: A No Nonsense GraphQL and REST Comparison:
https://www.youtube.com/watch?v=vgm_uGmspMI
Zdeněk Němec: REST vs. GraphQL: A Critical Review
https://blog.goodapi.co/rest-vs-graphql-a-critical-review-5f77392658e7
REST je jako objednat si v
RESTauraci. GraphQL je jako
sestavit si jídlo ze švédského stolu.
8. REST je obecný koncept
REST je soubor obecných myšlenek – mohou jej naplňovat různé podoby API. To
může být problém, protže spoustu rozhodnutí musí udělat ten, kdo to
implementuje. A tak může spoustu věci udělat špatně.
Je třeba rozumět konceptům REST a HTTP. A pokud nechci používat koncepty
RESTu – třeba hypermedia, tak stejně nemůžete postavit REST API.
10. Orientovaný na resource
Unikátní URL pro každou resource:
– /articles/c4b12316-cb13-11e8-a8d5-f2801f1b9f/
– /articles/1337/
– /articles/1337/comments/3383b04c/
Resource = podstatné jméno
11. Využívá HTTP protokol
HTTP metody = pojmenování operací nad resources
GET = načíst resource, nic se nemění
– GET https://blog/articles/1337/
POST = vytvořit novou resource (zpravidla nevíme její ID)
– POST https://blog/articles/
PUT = update (přepsání) celé resource
– PUT https://blog/articles/1337/
DELETE = mazání
– DELETE https://blog/articles/1337/
PATCH = částečný update
– PATCH https://blog/articles/1337/
Ale nejen HTTP metody – REST využívá i další části standardní HTTP
infrastruktury: cachování, hlavičky...
15. JSON API 1.0 (2015-05-29)
Konvence, jak správně řešit různé faktory REST API
Předchází znovuvynalézání kola
JSON API je zhmotnění řady best practices pro tvorbu REST API.
Popisuje, jak řešit plno věcí, které můžeme v API potřebovat.
22. Chyby
{
"errors": [
{ // všechna pole jsou volitelná 👌
"id": "37d5e868-ad31", // Unikátní ID této chyby
"status": "422", // HTTP status kód
"code": "API-13B", // Vlastní chybový kód
// Lidsky čitelný popis, který se pro stejnou chybu nemění:
"title": "Invalid value",
// Lidský detail chyby, může být lokalizovaný (jako title):
"detail": "First name must contain at least three characters.",
// zdroj chyby jako JSON pointer (RFC 6901)
"source": { "pointer": "/data/attributes/firstName" },
// Cokoliv, třeba stacktrace
"meta": { "file": "src/Controller/ArticleController.php"}
}
]
}
23. Složené (compound) dokumenty
GET /api/articles/1337
{
"data": {
"type": "articles",
"id": "1337",
"relationships": {
"author": {
"links": {
"self": "/articles/1337/relationships/author",
"related": "/articles/1337/author"
},
"data": { "type": "people", "id": "333" }
}
}
},
}
"included": [
{
"type": "people",
"id": "333",
"attributes": { "firstName": "John", "lastName": "Doe" },
"links": { "self": "/people/333" }
}
]
Resource z relationship můžeme najít v cache či v
identity mapě (podle jejího type a id). Když ji nemáme,
můžeme si ji načíst z jejího linku. Ale když bychom
potřebovali ušetřit requesty (N+1 problém), může nám
pomoci tzv. sideloading, kdy odpověď ten dokument
rovnou obsahuje („compound“ dokument).
24. Stránkování
Filtrování ¯_( ツ )_/¯
– jen rezervovaný query parametr filter, nic víc
Řazení
Sparse fileds – definice položek, které chci vrátit
– GET /articles?fields[articles]=title,body
Co dále umí JSON API řešit
Možnost říct si, jaké položky je přece unikátní vlastnost GraphQL!
Oh wait, v RESTu to jde taky. 🤔
26. github.com/json-api-php/json-api
$document = new DataDocument(
new ResourceObject(
'articles', // type
'1337', // id
// ... a jaké další chceme položky:
new Attribute('title', 'Article Title'),
new ToOne( // relationship
'author',
new ResourceIdentifier('author', '333'),
new SelfLink('/articles/1337/relationships/author'),
new RelatedLink('/articles/1337/author')
)
)
);
echo json_encode($document);
●
Jenom imutabilní datové entity JSON API formátu
●
To nejsnazší, co může každý u nového API udělat
28. github.com/json-api-php/json-api
$errorDocument = new ErrorDocument(
new Error(
new Status('404'),
new Code('not_found'),
new Title('Resource not found'),
new Detail('We tried hard but could not find it 😞'),
)
);
echo json_encode($errorDocument);
{
"errors": [
{
"status": "404",
"code": "not_found",
"title": "Resource not found",
"detail": "We tried hard but could not find it "
}
]
}
29. # config/routes.yaml
json_api:
resource: "@EnmJsonApiServerBundle/Resources/config/routing.xml"
GET /{type}
GET /{type}/{id}
GET /{type}/{id}/relationships/{relationship}
GET /{type}/{id}/{relationship}
POST /{type}
PATCH /{type}/{id}
DELETE /{type}/{id}
POST /{type}/{id}/relationships/{relationship}
PATCH /{type}/{id}/relationships/{relationship}
DELETE /{type}/{id}/relationships/{relationship}
eosnewmedia/json-api-server-bundle
●
Bundle pro Symfony
●
Request/response, exception listener...
31. // src/RequestHandler/ArticlesRequestHandler.php
class ArticlesRequestHandler implements RequestHandlerInterface
{
use NoRelationshipFetchTrait;
use NoRelationshipModificationTrait;
use NoResourceDeletionTrait;
public function fetchResource(RequestInterface $request): ResponseInterface
{
$resource = new JsonResource(
'articles', // type
$request->id(), // id
$this->repository->find($request->id())->toArray() // attributes
);
$document = new Document($resource);
return new DocumentResponse($document, [/* extra headers */], 200);
}
public function fetchResources(RequestInterface $request): ResponseInterface
{ /* ... */ }
public function createResource(RequestInterface $request): ResponseInterface
{ /* ... */ }
public function patchResource(RequestInterface $request): ResponseInterface
{ /* ... */ }
}
eosnewmedia/json-api-server-bundle
32. // src/RequestHandler/ArticlesRequestHandler.php
class ArticlesRequestHandler implements RequestHandlerInterface
{
use NoRelationshipFetchTrait;
use NoRelationshipModificationTrait;
use NoResourceDeletionTrait;
public function fetchResource(RequestInterface $request): ResponseInterface
{
$resource = new JsonResource(
'articles', // type
$request->id(), // id
$this->repository->find($request->id())->toArray() // attributes
);
$document = new Document($resource);
return new DocumentResponse($document, [/* extra headers */], 200);
}
public function fetchResources(RequestInterface $request): ResponseInterface
{ /* ... */ }
public function createResource(RequestInterface $request): ResponseInterface
{ /* ... */ }
public function patchResource(RequestInterface $request): ResponseInterface
{ /* ... */ }
}
eosnewmedia/json-api-server-bundle
GET /{type}/{id}
GET /{type}
POST /{type}
PATCH /{type}/{id}
Traity na endpointy, které nepotřebujeme.
34. Specifikace http://jsonapi.org/
Phil Sturgeon
– blog https://blog.apisyouwonthate.com/
– knížka "Build APIs You Won't Hate"
Blogpost + talk "The Benefits of Using JSON API"
– https://nordicapis.com/the-benefits-of-using-json-api/
OpenAPI přednáška zítra, 10:00
– Boyan Yordanov: Beyond Documentation With OpenAPI
Další zdroje
35. REST API neumírá,
ale má nadále své místo
GraphQL je alternativní typ API,
který má své specifické použití
36. Pro vaše další REST API
zvažte použití JSON API
V PHP je na to plno nástrojů o/