@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