Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

symfony api-platform depth

So far we've been struggling with Symfony, Doctrine, and Serializer depth.

I'd like to be able to provide just one-level-depth JSON REST API with Symfony, allowing me to manage my "foreign key" and relation logic directly from the view.

GET /people/1

{
  id:1,
  name:"theonewhoknocks",
  friends: [3, 12, 25]
}

Using FosRESTBundle, we've been strugling at succeeding on that. (we've seen "depth" anotations and "groups" views for models, but none of this fit our need).

The question is simple, before we make a choice for our future API, we have to know:

is api-platform able to provide a dead simple one level (with apparent foreign keys) REST API ?

like image 611
Cyril CHAPON Avatar asked Oct 11 '25 18:10

Cyril CHAPON


1 Answers

API Platform can handle that using the Serializer Symfony bundle and its annotation set.

To define what will be returned by an operation we use a normalizationContext which define group(s) of property to include in result of an api operation. Property to include have then this group name linked to @Groups serializer annotation

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
 * @ORM\Entity()
 * @ApiResource(normalizationContext={"groups"={"read"}}
 */
class Book {
    /**
     * @ORM\Column()
     * @Groups({"read"})
     */
    private $title;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="books")
     * @Groups({"read"})
     */
    private $author;

    /**
     * Will not be included in result
     */
    private $secret_comment;

}

If a relation column is in a Group as $author here, properties defined in a group in the child class will be included in the result

/**
 * @ORM\Entity()
 * @ApiResource(normalizationContext={"groups"={"read"}})
 */
class User {
    /**
     * @ORM\Column()
     * @Groups({"read"})
     */
    private $username;
}

In order to avoid cyclic recursion you can specify the max depth of child relation joins with annotation @MaxDepth(n) where n is the max depth (1 in your case). This annotation has to be enabled with enable_max_depth property in serializer context of the @ApiResource annotation

/**
 * @ApiPlatform(normalizationContext={"groups"={"read"}, "enable_max_depth"=true})
 */
class Book {
    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="books")
     * @Groups({"read"})
     * @MaxDepth(1)
     */
    private $author;
}

Please note that API Platform is in this case an agregation of existing bundles and features. Refer to the main bundles for detailed informations (here the Symfony Serializer bundle)

like image 108
Nicolas Janel Avatar answered Oct 15 '25 18:10

Nicolas Janel