SlideShare une entreprise Scribd logo
1  sur  37
Télécharger pour lire hors ligne
… možná nepotřebujete GraphQL
phpCE, 27. října 2018
Ondřej Machulda
 @OndraM
Anotovaná verze slajdů
GraphQL API?
Zdroj: https://twitter.com/samerbuna/status/644548922979954688
Ovládne GraphQL svět? Je REST API mrtvé? Už tři roky?
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.
GraphQL
Zdroj: https://twitter.com/tomdale/status/786954892342681600
GraphQL ale není náhrada REST. Není to REST 2.0.
Je to (zjednodušeně řečeno) další paradigma pro API.
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í.
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.
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.
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.
Vlastnosti REST API
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
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...
HATEOAS
Hypermedia as the Engine of Application State
Čím na webu hyperlinky,
tím v API hypermedia
HATEOAS
Hypermedia as the Engine of Application State
{
"articleId": 1337,
"title": "Article Title",
"text": "Lorem ipsum",
"links": [
{
"href": "/1337/comments",
"rel": "comments",
"type": "GET"
},
{
"href": "/1337/tags",
"rel": "tags",
"type": "GET"
}
]
}
https://jsonapi.org/
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.
GET /api/articles
Accept: application/vnd.api+json
---
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
…
}
Request / response
GET /api/articles/1337
{
"data": {
"type": "articles",
"id": "1337",
"attributes": {
"title": "Article title",
"datePublished": "2018-10-27T13:33:30",
}
}
}
Single resource object
Kolekce resource objectů
GET /api/articles
{
"data": [
{
"type": "articles",
"id": "1337",
"attributes": {
"title": "Article title"
}
},
{
"type": "articles",
"id": "1338",
"attributes": {
"title": "Another article title"
}
}
]
}
Vytváření resources
POST /api/articles
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data":
{
"type": "articles",
"attributes": {
"title": "New article"
}
}
}
Vytváření resources
HTTP/1.1 201 Created
Content-Type: application/vnd.api+json
Location: https://blog/articles/1339
{
"data":
{
"type": "articles",
"id": "1339",
"attributes": {
"title": "New article"
}
}
}
Další CRUD operace, HTTP kódy aj. viz jsonapi.org/format/#crud
Hypermedia
GET /api/articles/1337
{
"data": {
"type": "articles",
"id": "1337",
"attributes": { "title": "Article title" },
"relationships": {
"author": {
"links": {
"self": "https://blog/articles/1337/relationships/author",
"related": "https://blog/articles/1337/author"
}
},
"comments": {
"links": {
"self": "https://blog/articles/1/relationships/comments",
"related": "https://blog/articles/1/comments"
}
}
}
}
}
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"}
}
]
}
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).
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. 🤔
Nástroje pro JSON API v PHP
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
github.com/json-api-php/json-api
{
"data": {
"type": "articles",
"id": "1337",
"attributes": {
"title": "Article Title"
},
"relationships": {
"author": {
"data": {
"type": "author",
"id": "333"
},
"links": {
"self": "/articles/1337/relationships/author",
"related": "/articles/1337/author"
}
}
}
}
}
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 "
}
]
}
# 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...
# config/services.yaml
AppRequestHandlerArticlesRequestHandler:
tags:
- { name: json_api_server.request_handler, type: 'articles' }
eosnewmedia/json-api-server-bundle
// 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
// 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.
JSON API Playground
https://jsonapiplayground.reyesoft.com/
JSON API Implementations
https://jsonapi.org/implementations/
Další nástroje
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
REST API neumírá,
ale má nadále své místo
GraphQL je alternativní typ API,
který má své specifické použití
Pro vaše další REST API
zvažte použití JSON API
V PHP je na to plno nástrojů o/
joind.in/talk/9d53c
🔝 feedback 🙏
 Ondřej Machulda
 ondrejmachulda.cz
 @OndraM

Contenu connexe

Similaire à JSON API: Možná nepotřebujete GraphQL

Pavel ungr designed_for_seo
Pavel ungr designed_for_seoPavel ungr designed_for_seo
Pavel ungr designed_for_seo
H1.cz
 
Seo Pro Drupal Developery
Seo Pro Drupal DeveloperySeo Pro Drupal Developery
Seo Pro Drupal Developery
Jozef Toth
 
20110511 Vývoj software - produktivně, efektivně, kvalitně
20110511 Vývoj software - produktivně, efektivně, kvalitně20110511 Vývoj software - produktivně, efektivně, kvalitně
20110511 Vývoj software - produktivně, efektivně, kvalitně
Jiří Mareš
 
Python v PostgreSQL pohledem PHP programátora
Python v PostgreSQL pohledem PHP programátoraPython v PostgreSQL pohledem PHP programátora
Python v PostgreSQL pohledem PHP programátora
Michal Špaček
 
EZproxy a Shibboleth - Seminar v NTK 20.10.10
EZproxy a Shibboleth - Seminar v NTK 20.10.10EZproxy a Shibboleth - Seminar v NTK 20.10.10
EZproxy a Shibboleth - Seminar v NTK 20.10.10
Petr
 
Linked Data pro Evropský sociální fond
Linked Data pro Evropský sociální fondLinked Data pro Evropský sociální fond
Linked Data pro Evropský sociální fond
Martin Necasky
 
06 prez6(tvorba webu)
06 prez6(tvorba webu)06 prez6(tvorba webu)
06 prez6(tvorba webu)
olc_user
 

Similaire à JSON API: Možná nepotřebujete GraphQL (20)

TwigX: pište PHP šablony jako v Reactu
TwigX: pište PHP šablony jako v ReactuTwigX: pište PHP šablony jako v Reactu
TwigX: pište PHP šablony jako v Reactu
 
Vytvořeno pro SEO (Designed for SEO)
Vytvořeno pro SEO (Designed for SEO)Vytvořeno pro SEO (Designed for SEO)
Vytvořeno pro SEO (Designed for SEO)
 
Pavel ungr designed_for_seo
Pavel ungr designed_for_seoPavel ungr designed_for_seo
Pavel ungr designed_for_seo
 
EZproxy Seminar Multidata
EZproxy Seminar MultidataEZproxy Seminar Multidata
EZproxy Seminar Multidata
 
MoroSystems na ostravském CZJUGu o Apache Wicket
MoroSystems na ostravském CZJUGu o Apache WicketMoroSystems na ostravském CZJUGu o Apache Wicket
MoroSystems na ostravském CZJUGu o Apache Wicket
 
Seo Pro Drupal Developery
Seo Pro Drupal DeveloperySeo Pro Drupal Developery
Seo Pro Drupal Developery
 
CQRS v rohlik.cz
CQRS v rohlik.czCQRS v rohlik.cz
CQRS v rohlik.cz
 
20110511 Vývoj software - produktivně, efektivně, kvalitně
20110511 Vývoj software - produktivně, efektivně, kvalitně20110511 Vývoj software - produktivně, efektivně, kvalitně
20110511 Vývoj software - produktivně, efektivně, kvalitně
 
Techniky a nástroje pro propojená data (Linked Data)
Techniky a nástroje pro propojená data (Linked Data)Techniky a nástroje pro propojená data (Linked Data)
Techniky a nástroje pro propojená data (Linked Data)
 
TNPW2-2011-03
TNPW2-2011-03TNPW2-2011-03
TNPW2-2011-03
 
Google App Engine
Google App EngineGoogle App Engine
Google App Engine
 
OAuth 2.0 a Zend Framework
OAuth 2.0 a Zend FrameworkOAuth 2.0 a Zend Framework
OAuth 2.0 a Zend Framework
 
Python v PostgreSQL pohledem PHP programátora
Python v PostgreSQL pohledem PHP programátoraPython v PostgreSQL pohledem PHP programátora
Python v PostgreSQL pohledem PHP programátora
 
EZproxy a Shibboleth - Seminar v NTK 20.10.10
EZproxy a Shibboleth - Seminar v NTK 20.10.10EZproxy a Shibboleth - Seminar v NTK 20.10.10
EZproxy a Shibboleth - Seminar v NTK 20.10.10
 
API Obludárium (API 2018, Praha)
API Obludárium (API 2018, Praha)API Obludárium (API 2018, Praha)
API Obludárium (API 2018, Praha)
 
SEO Restart 2023: Lukáš Kostka - AI a R studio – optimalizace meta tagů na ,,...
SEO Restart 2023: Lukáš Kostka - AI a R studio – optimalizace meta tagů na ,,...SEO Restart 2023: Lukáš Kostka - AI a R studio – optimalizace meta tagů na ,,...
SEO Restart 2023: Lukáš Kostka - AI a R studio – optimalizace meta tagů na ,,...
 
Screen scraping se ScraperWiki (Jindřich Mynarz)
Screen scraping se ScraperWiki (Jindřich Mynarz)Screen scraping se ScraperWiki (Jindřich Mynarz)
Screen scraping se ScraperWiki (Jindřich Mynarz)
 
vSphere automation workshop python
vSphere automation workshop pythonvSphere automation workshop python
vSphere automation workshop python
 
Linked Data pro Evropský sociální fond
Linked Data pro Evropský sociální fondLinked Data pro Evropský sociální fond
Linked Data pro Evropský sociální fond
 
06 prez6(tvorba webu)
06 prez6(tvorba webu)06 prez6(tvorba webu)
06 prez6(tvorba webu)
 

Plus de Ondřej Machulda

Plus de Ondřej Machulda (12)

Selenium a WebDriver - přítomnost a budoucnost
 Selenium a WebDriver - přítomnost a budoucnost  Selenium a WebDriver - přítomnost a budoucnost
Selenium a WebDriver - přítomnost a budoucnost
 
Trendy a nové možnosti test automation
Trendy a nové možnosti test automationTrendy a nové možnosti test automation
Trendy a nové možnosti test automation
 
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
 
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
 
Funkční testování – chybějící vrchol pyramidy (WebExpo 2016)
Funkční testování – chybějící vrchol pyramidy (WebExpo 2016)Funkční testování – chybějící vrchol pyramidy (WebExpo 2016)
Funkční testování – chybějící vrchol pyramidy (WebExpo 2016)
 
Automatické testování webů v praxi - Barcamp Ostrava 2015
Automatické testování webů v praxi - Barcamp Ostrava 2015Automatické testování webů v praxi - Barcamp Ostrava 2015
Automatické testování webů v praxi - Barcamp Ostrava 2015
 
Jak jsme přepisovali Jobs.cz na Symfony
Jak jsme přepisovali Jobs.cz na SymfonyJak jsme přepisovali Jobs.cz na Symfony
Jak jsme přepisovali Jobs.cz na Symfony
 
Optimistic/Pessimistic Offline Lock
Optimistic/Pessimistic Offline LockOptimistic/Pessimistic Offline Lock
Optimistic/Pessimistic Offline Lock
 
Hlavní problémy systému on-line rezervace vstupenek do O2 Areny
Hlavní problémy systému on-line rezervace vstupenek do O2 ArenyHlavní problémy systému on-line rezervace vstupenek do O2 Areny
Hlavní problémy systému on-line rezervace vstupenek do O2 Areny
 
Testování systému pro on-line rezervaci vstupenek do O2 Areny
Testování systému pro on-line rezervaci vstupenek do O2 ArenyTestování systému pro on-line rezervaci vstupenek do O2 Areny
Testování systému pro on-line rezervaci vstupenek do O2 Areny
 
Pionýr - stručná historie organizace
Pionýr - stručná historie organizacePionýr - stručná historie organizace
Pionýr - stručná historie organizace
 
Raid
RaidRaid
Raid
 

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.
  • 4. GraphQL Zdroj: https://twitter.com/tomdale/status/786954892342681600 GraphQL ale není náhrada REST. Není to REST 2.0. Je to (zjednodušeně řečeno) další paradigma pro API.
  • 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...
  • 12. HATEOAS Hypermedia as the Engine of Application State Čím na webu hyperlinky, tím v API hypermedia
  • 13. HATEOAS Hypermedia as the Engine of Application State { "articleId": 1337, "title": "Article Title", "text": "Lorem ipsum", "links": [ { "href": "/1337/comments", "rel": "comments", "type": "GET" }, { "href": "/1337/tags", "rel": "tags", "type": "GET" } ] }
  • 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.
  • 16. GET /api/articles Accept: application/vnd.api+json --- HTTP/1.1 200 OK Content-Type: application/vnd.api+json { … } Request / response
  • 17. GET /api/articles/1337 { "data": { "type": "articles", "id": "1337", "attributes": { "title": "Article title", "datePublished": "2018-10-27T13:33:30", } } } Single resource object
  • 18. Kolekce resource objectů GET /api/articles { "data": [ { "type": "articles", "id": "1337", "attributes": { "title": "Article title" } }, { "type": "articles", "id": "1338", "attributes": { "title": "Another article title" } } ] }
  • 19. Vytváření resources POST /api/articles Accept: application/vnd.api+json Content-Type: application/vnd.api+json { "data": { "type": "articles", "attributes": { "title": "New article" } } }
  • 20. Vytváření resources HTTP/1.1 201 Created Content-Type: application/vnd.api+json Location: https://blog/articles/1339 { "data": { "type": "articles", "id": "1339", "attributes": { "title": "New article" } } } Další CRUD operace, HTTP kódy aj. viz jsonapi.org/format/#crud
  • 21. Hypermedia GET /api/articles/1337 { "data": { "type": "articles", "id": "1337", "attributes": { "title": "Article title" }, "relationships": { "author": { "links": { "self": "https://blog/articles/1337/relationships/author", "related": "https://blog/articles/1337/author" } }, "comments": { "links": { "self": "https://blog/articles/1/relationships/comments", "related": "https://blog/articles/1/comments" } } } } }
  • 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. 🤔
  • 25. Nástroje pro JSON API v PHP
  • 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
  • 27. github.com/json-api-php/json-api { "data": { "type": "articles", "id": "1337", "attributes": { "title": "Article Title" }, "relationships": { "author": { "data": { "type": "author", "id": "333" }, "links": { "self": "/articles/1337/relationships/author", "related": "/articles/1337/author" } } } } }
  • 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...
  • 30. # config/services.yaml AppRequestHandlerArticlesRequestHandler: tags: - { name: json_api_server.request_handler, type: 'articles' } eosnewmedia/json-api-server-bundle
  • 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.
  • 33. JSON API Playground https://jsonapiplayground.reyesoft.com/ JSON API Implementations https://jsonapi.org/implementations/ Další nástroje
  • 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/
  • 37. joind.in/talk/9d53c 🔝 feedback 🙏  Ondřej Machulda  ondrejmachulda.cz  @OndraM