How to implement custom item get endpoint with filtering in api platform?

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
{
    // ...

    /**
     * @ORMOneToMany(targetEntity=MatchPlayer::class, mappedBy="user")
     */
    private $matches;

    // ...
}

MatchPlayer.php

class MatchPlayer
{
    // ...

    /**
     * @ORMManyToOne(targetEntity=User::class, inversedBy="matches")
     * @ORMJoinColumn(onDelete="SET NULL")
     */
    private $user;

    /**
     * @ORMManyToOne(targetEntity=Match::class, inversedBy="players")
     */
    private $playedMatch;

    /**
     * @ORMManyToOne(targetEntity=Position::class, inversedBy="matches")
     */
    private $position;

    // ...
}

Match.php

class Match
{
    // ...

    /**
     * @ORMColumn(type="smallint")
     * @Groups({"match:read"})
     */
    private $outcome;

    /**
     * @ORMManyToOne(targetEntity=Sport::class, inversedBy="matches")
     */
    private $sport;

    /**
     * @ORMOneToMany(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.

Source: Symfony Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *