@matarld
@matarld
mtarld
les-tilleuls.coop
@matarld
@matarld
REST -Principles
@matarld
End of the presentation, press any key to exit...
@matarld
(that we can access from another resource)
@matarld
@matarld
Last minute feature
@matarld
GET /players?team=france@matarld
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
#[ApiResource]
+ #[ApiFilter(SearchFilter::class, properties: ['team.id' => 'exact'])]
class Player
{
// ...
}@matarld
GET /players?team=thatsatypo{
"@type": "hydra:Collection",
"hydra:member": []
}@matarld
GET /players?team=francethe player resources
that belongs to france team
@matarld
resource
subresource
GET /teams/france/players@matarld
- API Platform and subresources -
@matarld
PATCH /teams/france/players/dupont
GET /teams/france/players/dupont
GET /teams/france/players
DELETE /teams/france/players/dupont
PUT /teams/france/players/dupont
POST /teams/france/players
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
#[ApiResource]
class Team
{
#[ApiSubresource]
private Collection $players;
// ...
}use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
#[ApiResource]
class Team
{
#[ApiSubresource]
private Collection $players;
// ...
}@matarld
use ApiPlatform\Metadata\{ApiResource,Get,GetCollection,Link};
#[ApiResource]
#[GetCollection(
uriTemplate: '/teams/{teamId}/players',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, toProperty: 'team'),
],
)]
#[Get(
uriTemplate: '/teams/{teamId}/players/{playerId}',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, toProperty: 'team'),
'playerId' => new Link(fromClass: Player::class),
],
)]
class Player
{
public Team $team;
}GET /playersGET /players/{p}POST /playersPUT /players/{p}PATCH /players/{p}DELETE /players/{p}GET /teams/{t}/playersGET /teams/{t}/players/{p}@matarld
uriTemplate: '/teams/{teamId}/players',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, toProperty: 'team'),
],@matarld
{
"@type": "hydra:Collection",
"hydra:member": [
{"@id": "/players/dupont"},
{"@id": "/players/fickou"}
]
}@matarld
#[ApiResource]
#[GetCollection('/teams/{teamId}/players')]
#[Get('/teams/{teamId}/players/{playerId}')]
class Player
{
public Team $team;
}#[Get]
#[GetCollection]
#[Put]
#[Patch]
#[Post]
#[Delete]
#[GetCollection('/teams/{teamId}/players')]
#[Get('/teams/{teamId}/players/{playerId}')]
class Player
{
public Team $team;
}@matarld
#[GetCollection(
uriTemplate: '/teams/{teamId}/players',
+ itemUriTemplate: '/teams/{teamId}/players/{playerId}',
)]#[Get]
#[GetCollection]
#[Put]
#[Patch]
#[Post]
#[Delete]
#[GetCollection('/teams/{teamId}/players')]
#[Get('/teams/{teamId}/players/{playerId}')]
class Player
{
public Team $team;
}@matarld
{
"@type": "hydra:Collection",
"hydra:member": [
{"@id": "/teams/france/players/dupont"},
{"@id": "/teams/france/players/fickou"}
]
}@matarld
resources:
App\Entity\Player:
operations:
ApiPlatform\Metadata\GetCollection:
uriTemplate: /teams/{teamId}/players
uriVariable:
teamId: { fromClass: App\Entity\Team, toProperty: team }
itemUriTemplate: /teams/{teamId}/players/{playerId}
ApiPlatform\Metadata\Get:
uriTemplate: /teams/{teamId}/players/{playerId}
uriVariable:
teamId: { fromClass: App\Entity\Team, toProperty: team }
playerId: { fromClass: App\Entity\Player }@matarld
Urging feature
@matarld
GET /players/{playerId}/sprintsGET /players/{playerId}/sprints/{sprintId}@matarld
#[GetCollection(
uriTemplate: '/players/{playerId}/sprints',
uriVariables: [
'playerId' => new Link(fromClass: Player::class, toProperty: 'player'),
],
itemUriTemplate: '/players/{playerId}/sprints/{sprintId}',
)]
class Sprint
{
public Player $player;
}@matarld
#[GetCollection(
uriTemplate: '/players/{playerId}/sprints',
uriVariables: [
'playerId' => new Link(fromClass: Player::class, toProperty: 'player'),
],
itemUriTemplate: '/players/{playerId}/sprints/{sprintId}',
)]
#[Get(
uriTemplate: '/players/{playerId}/sprints/{sprintId}',
uriVariables: [
'playerId' => new Link(fromClass: Player::class, toProperty: 'player'),
'sprintId' => new Link(fromClass: Sprint::class),
],
)]
class Sprint
{
public Player $player;
}@matarld
#[Get(
+ status: 404,
uriTemplate: '/players/{playerId}/sprints/{sprintId}',
- uriVariables: [
- 'playerId' => new Link(fromClass: Player::class, toProperty: 'player'),
- 'sprintId' => new Link(fromClass: Sprint::class),
- ],
)]@matarld
#[Get(
status: 404,
+ openApi: false,
uriTemplate: '/players/{playerId}/sprints/{sprintId}',
)]@matarld
#[NotExposed(
uriTemplate: '/players/{playerId}/sprints/{sprintId}',
)]@matarld
Very important feature
@matarld
GET /stadium/gerland/matches/fr-nz/orders/001/lines/a6b993249c88/seats
Stadiums
Matches
Orders
Order lines
Seats
@matarld
GET /matches/fr-nz/orders
1
30000
90000
GET /orders/{order}/lines1+N
GET /lines/{line}/seats1+N+Σɴ(M)
@matarld
GET /seats?stadium=gerland&match=fr-nz&status=sold
1
@matarld
Last feature
@matarld
POST /teams/italy/injuries@matarld
#[Post(
uriTemplate: '/teams/{teamId}/injuries',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, toProperty: 'team'),
],
)]
class Injury
{
public Team $team;
}@matarld
{
"player": "/players/ceccarelli",
"type": "sprain",
"duration": 10,
"team": "/teams/italy"
}POST /teams/italy/injuries
"/teams/italy"/teams/italy@matarld
{
"player": "/players/ceccarelli",
"type": "sprain",
"duration": 10
}POST /teams/italy/injuries
/teams/italy@matarld
#[Post(
uriTemplate: '/teams/{teamId}/injuries',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, toProperty: 'team'),
],
)]@matarld
#[Post(
uriTemplate: '/teams/{teamId}/injuries',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, toProperty: 'team'),
],
+ extraProperties: [
+ 'parent_uri_template' => '/teams/{teamId}',
+ ],
)]@matarld
The very last feature
@matarld
#[Get]
class Match
{
public string $score;
/** @var list<Event> */
public array $events;
}@matarld
{
"@id": "/matches/fr-nz",
"score": "27-13",
"events": [
{
"@id": "/events/97b470a",
"actor": "https://schema.org/Referee",
"value": "https://ffr.fr/enums/events/kick_off"
},
{
"@id": "/events/46a0368",
"actor": "https://schema.org/Player",
"value": "https://ffr.fr/enums/events/hit_ball"
},
{...}
]
}@matarld
#[Get]
class Match
{
public string $score;
/** @var list<Event> */
+ #[ApiProperty(readableLink: false)]
public array $events;
}@matarld
{
"@id": "/matches/fr-nz",
"score": "27-13",
"events": [
"/events/97b470a",
"/events/46a0368",
"..."
]
}@matarld
#[Get]
class Match
{
public string $score;
/** @var list<Event> */
- #[ApiProperty(readableLink: false)]
+ #[ApiProperty(uriTemplate: '/matches/{id}/events')]
public array $events;
}@matarld
{
"@id": "/matches/fr-nz",
"score": "27-13",
"events": "/matches/fr-nz/events"
}{
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/matches/fr-nz/events/97b470a",
"actor": "https://schema.org/Referee",
"value": "https://ffr.fr/enums/events/kick_off"
},
{
"@id": "/matches/fr-nz/events/46a0368",
"actor": "https://schema.org/Player",
"value": "https://ffr.fr/enums/events/hit_ball"
},
{...}
]
}?preload=/events
@matarld
The ultimate last feature (pinky promise!)
@matarld
GET /teams/france/sponsors/le-coq-sportif@matarld
GET /teams/france/sponsors/le-coq-sportifGET /sponsors/le-coq-sportif@matarld
#[Get]
#[Get(
uriTemplate: '/teams/{teamId}/sponsors/{sponsorId}',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, fromProperty: 'sponsor'),
'sponsorId' => new Link(fromClass: Sponsor::class),
],
)]
class Sponsor
{
}@matarld
#[Get]
#[Get(
+ status: 301
uriTemplate: '/teams/{teamId}/sponsors/{sponsorId}',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, fromProperty: 'sponsor'),
'sponsorId' => new Link(fromClass: Sponsor::class),
],
)]
class Sponsor
{
}@matarld
@matarld
#[Get]
#[Get(
status: 301
uriTemplate: '/teams/{teamId}/sponsors/{sponsorId}',
uriVariables: [
'teamId' => new Link(fromClass: Team::class, fromProperty: 'sponsor'),
'sponsorId' => new Link(fromClass: Sponsor::class),
],
+ extraProperties: [
+ 'canonical_uri_template' => '/sponsors/{sponsorId}',
+ ],
)]
class Sponsor
{
}@matarld