SEPTEMBER 21-22, 2023 - LILLE, FRANCE & ONLINE
REVOLUTION
RELEASE CYCLE
2.7 / 3.0
3.2
4.x
2021
Today
2024
RELEASE CYCLE
3.0
3.2
4.x
2021
2024
3.1
244 commits
279 commits
cool stuff
3.3
Today
RIP 2.7
Tomorrow at 14:00
3.0
API Platform is easier to get around, more intuitive and less restrictive
“
“
3.1
Deprecations and new features
Standard PUT
The HTTP specification states that PUT requests should create or replace the state defined by the representation enclosed in the request message content.
#[ApiResource(
operations: [new Get(), new Put(allowCreate: true)],
extraProperties: [
'standard_put' => true,
]
)]
#[Entity]
class Book {}
Standard PUT
# config/packages/api_platform.yaml
api_platform:
defaults:
extra_properties:
standard_put: true
Denormalization Errors
#[ApiResource(
collectDenormalizationErrors: true
)]
class Book {}
If the submitted data trigger denormalization errors, the HTTP status code will be set to 422 Unprocessable Content and the response body will contain the list of errors.
Denormalization Errors
{
"@type": "ConstraintViolationList",
"hydra:title": "An error occurred",
"hydra:description": "boolean: This value should be of type bool...",
"violations": [
{
"propertyPath": "bar",
"message": "This value should be of type bool."
},
{
"propertyPath": "foo",
"message": "This value should be of type string."
}
]
}
OpenAPI
#[Post(
openapi: false
)]
class Book {}
OpenAPI As Attributes
use ApiPlatform\OpenApi\Model as OpenApi;�
#[Post(
openapi: new OpenApi\Operation(
requestBody: new OpenApi\RequestBody(
content: new \ArrayObject([
'multipart/form-data' => [
'schema' => [
'type' => 'object',
'properties' => [
'file' => ['type' => 'string', 'format' => 'binary']
]
]
]
])
)
)
)]
OpenAPI Component
Subtree Split
Resource vs Doctrine Entity
namespace App\ApiResource;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Doctrine\Orm\State\Options;
use ApiPlatform\Metadata\ApiFilter;
use App\Entity\Book as BookEntity;
#[ApiResource(stateOptions: new Options(entityClass: BookEntity::class))]
class Book
{
public string $id;
#[ApiFilter(OrderFilter::class)]
public string $value;
}
Tomorrow at 09:00
And more…
Release notes: https://github.com/api-platform/core/releases/tag/v3.1.0
3.2
Deprecations and new features
Write support on alternate resources!
namespace App\Entity;
use ApiPlatform\State\CreateProvider;
use App\Entity\Company;
#[Post(
uriTemplate: '/companies/{id}/employees',
uriVariables: [
'id' => new Link(fromClass: Company::class, toProperty: 'employee'),
],
provider: CreateProvider::class,
)]
class Employee {}
IRI Customisation
#[GetCollection(
uriTemplate: '/companies',
itemUriTemplate: '/companies/{id}/employees/{id}'
)]
class Company {
/** @var Employee[] */
#[ApiProperty(uriTemplate: '/companies/{id}/employees')]
public array $employees;
}
Today at 17:00
z
URI Variables & Links
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Link;
#[Get(
uriTemplate: '/book/{title}',
uriVariables: ['title' => new Link(identifiers: ['title'])]
)]
#[ORM\Entity]
final class Book {}
Handle Links
use ApiPlatform\Doctrine\Orm\State\Options;
use Doctrine\ORM\QueryBuilder;
use ApiPlatform\Metadata\Get;
#[Get(
uriTemplate: '/book/{title}',
stateOptions: new Options(
handleLinks: fn(QueryBuilder $queryBuilder, array $identifiers) => {
$queryBuilder->andWhere("{$queryBuilder->getRootAliases()[0]}.title = :title");
$queryBuilder->setParameter('title', $identifiers['title']);
}
)
)]
#[ORM\Entity]
final class Book {}
JSON Problem
# config/packages/api_platform.yaml
api_platform:
defaults:
extra_properties:
rfc_7807_compliant_errors: true
Error Resource
use ApiPlatform\Metadata\ErrorResource;
use ApiPlatform\Metadata\Error;
#[ErrorResource(
uriTemplate: '/my_error/{id}',
status: 418,
openapi: false,
uriVariables: ['id'],
operations: [
new Error(outputFormats: ['jsonproblem' => ['application/problem+json']]),
]
)]
final class MyException implements ProblemExceptionInterface {}
Let’s Go Back In Time…
namespace Dunglas\JsonLdApiBundle\Controller;
class ResourceController extends Controller implements ResourceControllerInterface
{
public function getAction(Request $request, $id)
{
$object = $this->findOrThrowNotFound($id);
return new JsonLdResponse($this->normalize($object));
}
}
Then, Listeners were introduced…
API Platform 2
HTTP Kernel Listeners
API Platform relies on Symfony kernel listeners to handle Validation, Serialization, Security and data persistence.
PATCH /books/1
Content-Type: application/merge-patch+json
{"title": "API Platform"}
Kernel “request”
Kernel “view”
Why are listeners not ideal?
I love providers
MainController
<?php
use ApiPlatform\State\ProviderInterface;
use ApiPlatform\State\ProcessorInterface;
class MainController {
public function __invoke(ProviderInterface $provider, ProcessorInterface $processor) {
$body = $this->provider->provide($operation, $uriVariables, $context);
return $this->processor->process($body, $operation, $uriVariables, $context);
}
}
Composition with Providers and Processors
ReadProvider
SecurityProvider
DeserializeProvider
ValidateProcessor� WriteProcessor
SerializeProcessor
The Power Is Yours
bin/console debug:container api_platform.state_provider.access_checker
Allows access based on the �ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface.
This implementation covers GraphQL and HTTP.
�Service ID api_platform.state_provider.access_checker
Class ApiPlatform\Symfony\Security\State\AccessCheckerProvider
Usages api_platform.state_provider.access_checker.post_deserialize
api_platform.state_provider.deserialize
api_platform.state_provider.read
Goodbye Symfony Listeners
# config/packages/api_platform.yaml
api_platform:
event_listeners_backward_compatibility_layer: true # will be false in API Platform 4
And more…
# config/packages/api_platform.yaml
api_platform:
keep_legacy_inflector: true # will be false in API Platform 4
Release notes: https://github.com/api-platform/core/releases/tag/v3.2.0
3.2
Documentation Revolution
New Website!
Open source & Documentation
Can we use code as documentation ?
Guides
PHP + WASM = ❤️
What’s up next?
How we made API Platform compatible with Laravel 10-13-2023!
Be Ready For API Platform 4!
composer recipes:update
FOLLOW ME!
@s0yuka
soyuka.me
@soyuka@phpc.social
Thank you!
Any questions?
FOLLOW ME!
@JaneDoeTwitter
jane-doe.com
Amazing second part
Interesting introduction
Incredible third part
Another amazing part
A spectacular conclusion
01
02
03
04
05
01 - Interesting introduction
Some cool stuff
About me
Jane Doe
About me again
JANE DOE
@JaneDoeTwitter
jane-doe.com
Some code
{
"@context": "/contexts/ConstraintViolationList",
"@type": "ConstraintViolationList",
"hydra:title": "An error occurred",
"hydra:description": "isbn: This value is neither a valid ISBN-10 nor a valid ISBN-13.\ntitle: This value should not be blank.",
"violations": [
{
"propertyPath": "isbn",
"message": "This value is neither a valid ISBN-10 nor a valid ISBN-13."
},
{
"propertyPath": "title",
"message": "This value should not be blank."
}
]
}
Some title
Add your text here
Another example
Another example
Add something here
Another example
Another slide
Example
Some content you want to highlight
Another example
Another content to highlight
Add caption (or not)
Some title
Add your text here
Say something (or delete this)
Some title
Add your text here
Some title
Some interesting point
Another interesting point
A final interesting point
Some title
Some interesting point
A final interesting point
Another interesting point
You can say interesting
things here
Hello!
Thank you!
Hello!
Any questions?
@JaneDoeTwitter
jane-doe.com
Follow me on social media
Thank you!
Any questions?
FOLLOW ME!
@JaneDoeTwitter
jane-doe.com
Need graphic stuff for your slides?
Need graphic stuff for your slides?
Something cool