I am working on a symfony/api platform app that allows users to track sports matches. My entities look like this (shortened for brevity):
User.php
class User implements UserInterface
{
// ...
/**
* @ORM\OneToMany(targetEntity=MatchPlayer::class, mappedBy="user")
*/
private $matches;
// ...
}
MatchPlayer.php
class MatchPlayer
{
// ...
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="matches")
* @ORM\JoinColumn(onDelete="SET NULL")
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity=Match::class, inversedBy="players")
*/
private $playedMatch;
/**
* @ORM\ManyToOne(targetEntity=Position::class, inversedBy="matches")
*/
private $position;
// ...
}
Match.php
class Match
{
// ...
/**
* @ORM\Column(type="smallint")
* @Groups({"match:read"})
*/
private $outcome;
/**
* @ORM\ManyToOne(targetEntity=Sport::class, inversedBy="matches")
*/
private $sport;
/**
* @ORM\OneToMany(targetEntity=MatchPlayer::class, mappedBy="playedMatch", cascade={"persist", "remove"})
*/
private $players;
// ....
}
So in my model, a user can relate to many matches and a match can relate to many users via the glue table that also saves what position a user played.
Now I want to expose an endpoint with api platform like /api/users/{id}/statistics or /api/statistics/{userId} that fetches data dynamically and shows how many matches a user has played in which sport, on what position, and how many matches the user has won/tied/lost. Ideally, the endpoint would allow filtering by sports and would look something like /api/users/{id}/statistics?sport[]=football&sport[]&outcome=win for example.
Because these statistics don't get persisted to the database as an entity, I tried an approach similar to the Expose a model without any routes documentation page. I created a Statistics entity that looks like this:
/**
* @ApiResource(
* collectionOperations={},
* itemOperations={
* "get"={
* "controller"=NotFoundAction::class,
* "read"=false,
* "output"=false,
* },
* }
* )
*/
class Statistic
{
/**
* @var User
* @ApiProperty(identifier=true)
*/
public $user;
/**
* @var Position[]|null
*/
public $position = [];
/**
* @var Sport[]|null
*/
public $maps = [];
/**
* @var int
*/
public $wins = 0;
/**
* @var int
*/
public $ties = 0;
/**
* @var int
*/
public $losses = 0;
}
and added a custom operation to the User entity:
* @ApiResource(
* ...
* itemOperations={
* "get_statistic"={
* "method"="GET",
* "path"="/users/{id}/statistics",
* }
* },
* ...
*/
However I am not sure how to implement the filtering by sports, position and wins/ties/losses. A "normal" filter doesn't work as far as I know since its only applied to the get operation on collections.
If this is even possible, how would I implement this in my api? I already tried custom data providers and controllers, but I cant get the filter query parameters in either solution, and a "normal" filter (like api platforms built in SearchFilter) wont work since it is only applied to the get operation on collections, and I am dealing with an item.