Sylius and API Platform integration is the project that we started in early 2020. Since then, we were working hard designing, delivering and adjusting our new API. We've learned a lot and during my presentation, I would like to share our findings.
Why did we design our API this way?
What were our heuristics and what did we achieve?
How to design more complicated flows in API?
13. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
14. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
15. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
16. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
17. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
18. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
19. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
20. [short title of solved problem and solution]
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Date: [YYYY-MM-DD when the decision was last updated]
Context and Problem Statement
[Describe the context and problem statement]
Decision Drivers
[driver 1, e.g., a force, facing concern, …]
…
Considered Options
[option 1]
[example | description | pointer to more information | …]
Good, because [argument a]
Bad, because [argument b]
…
Decision Outcome
Chosen option: "[option 1]", because [justi
fi
cation].
References
[Link type] [Link to ADR]
…
28. sylius.com
28
✔ Solves over fetching and under fetching
By design
✔ Typed, nice documentation
? Sends everything with POST
It is possible to do it with GET
✔ Gracefully deprecation of queries
Which was not possible with default REST
GraphQL
29. sylius.com
29
✔ May solve over fetching and under fetching
With spare
fi
elds sets and/or Vulcain
✔ Typed, nice documentation
With OpenAPI
✔ Takes advantage of 20 years of web cache development
Fake date institute ™
✔ Gracefully deprecation of queries
With OpenAPI
REST
43. Version #1 - Adding
fi
elds on entity
class ShippingMethod
{
/** rest of methods */
public ?int $cost; // never used in app
// serialized only when possible to count
}
44. Version #2 - Read model
class CartShippingMethod
{
public function __construct(
public readonly string $code,
public readonly ShippingMethodInterface $shippingMethod,
public readonly int $cost
) {
}
}
51. sylius.com
51
✘ Available
fi
elds
Complicated serialisation groups depending on logged in user
✘ Hard to de
fi
ne identi
fi
ers
We have resigned from them later
✘ Requirement to de
fi
ne granular access control
To now allow to access sensitive date for non-admins
Findings
52. sylius.com
52
🛒 Shop has 72 endpoints
64% of read endpoints
🖊 Only 20% of resources have writable capabilities in shop
40% of them are never exposed in shop
⚙ Admin has 128 endpoints
52% of read endpoints
Data
53. Option #1 - Admin & Shop pre
fi
xed
/api/products/?admin
54. sylius.com
54
✔ Available
fi
elds
Depending on logged in user
✘ Seems wrong from the REST perspective
If we add pre
fi
x to the URL
✘ Requirement to de
fi
ne granular access control
To now allow to access sensitive date for non-admins
Findings
56. sylius.com
56
✔ Available
fi
elds
Depending on logged in user
✔ REST compilant
✘ Requirement to de
fi
ne granular access control
May be mitigated with Voters
Findings
✘ Not easily supported
By API Platform and Open API spec
57. Option #3 - Admin & Shop pre
fi
xed
/api/shop/products/
/api/admin/products/
58. sylius.com
58
✔ Available
fi
elds
Depending on logged in user
✔/✘ REST compilant
Disputable
✔ Straightforward access control
Just with security con
fi
g
Findings
✔ Easily supported
By API Platform and Open API spec
68. sylius.com
68
🔮 Versioning endpoints
With sunset header
🔮 Vendor added to accept header
application/vnd.sylius.v1+json
🔮 Deprecating endpoints,
fi
elds etc
In documentation of Open API
Future
86. sylius.com
86
✔ We are used to this separation
Mockups “force” such design
✔ Addressing requires state machine transition
While coupon appliance cart processing
✔ Di
ff
erent data required on di
ff
erent pages
Reasoning?
90. sylius.com
90
✔ UI Mockups should not force any design decision
We can preload data from more then one endpoint
✔ Don’t use state machine where there is none
✔ Either store data earlier or use partial update
Changed attitude
94. sylius.com
94
Use ADRs
And browse them from time to time
Custom logic? New API resource!
Let’s behave like a tax department!
REST will be with us for the long time
But GraphQL will be there as well
Do not map HTML based websites to your API
I know, it was obvious 😅