Rest 如何在API平台上使用继承的类
我希望使用API平台对对象层次结构类执行CRUD操作。我发现在API平台上使用继承类时写得很少,而在Symfony的序列化程序中使用继承类时写得不多,我正在寻找更好的方向,特别是对于继承类,需要以不同的方式实现什么 假设我有狗、猫和老鼠,它们都是从抽象动物(见下文)继承来的。这些实体是使用Rest 如何在API平台上使用继承的类,rest,symfony,doctrine-orm,api-platform.com,jms-serializer,Rest,Symfony,Doctrine Orm,Api Platform.com,Jms Serializer,我希望使用API平台对对象层次结构类执行CRUD操作。我发现在API平台上使用继承类时写得很少,而在Symfony的序列化程序中使用继承类时写得不多,我正在寻找更好的方向,特别是对于继承类,需要以不同的方式实现什么 假设我有狗、猫和老鼠,它们都是从抽象动物(见下文)继承来的。这些实体是使用bin/console make:entity创建的,仅被修改以扩展父类(以及它们各自的存储库)并添加Api平台注释 组应该如何与继承的类一起使用?是否每个子类(即狗、猫、老鼠)都有自己的组,还是只使用父类动物
bin/console make:entity
创建的,仅被修改以扩展父类(以及它们各自的存储库)并添加Api平台注释
组应该如何与继承的类一起使用?是否每个子类(即狗、猫、老鼠)都有自己的组,还是只使用父类动物组?当对所有人使用animal
组时,某些路由响应连接关系的总数已超过指定的最大值代码>,混合时,有时会得到预期的关联名称,'miceEaten'不是关联。
。这些组是否也允许父实体上的APIProperty应用于子实体(即Animal::weight的默认openapi_上下文示例值为1000)
API平台没有讨论CTI或STI,我在文档中找到的唯一相关参考是关于。除了CLI或STI之外,还需要使用MappedSuperclass吗?请注意,我尝试将MappedSuperclass
应用于Animal
,但收到了预期的错误
基于其他方面,似乎首选的RESTful实现是使用单个端点/animals
,而不是单个/dogs
、/cats
和/mice
。同意吗?如何使用API平台实现这一点?如果@apirource()
注释仅应用于动物,则我会得到一个所需的URL,但在OpenAPI Swagger文档或实际请求中没有得到Dog、Cat和Mouse的子属性。如果@apirource()
注释仅应用于狗、猫和老鼠,则无法获得所有动物的组合集合,我有多个端点。是否需要将其应用于所有三种情况?OpenApi的关键字oneOf
、allOf
和anyOf
似乎可以提供这样一个解决方案。Api平台是否支持此功能?如果支持,如何支持
畜生
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use App\Repository\AnimalRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={"get", "post"},
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"animal:read", "dog:read", "cat:read", "mouse:read"}},
* denormalizationContext={"groups"={"animal:write", "dog:write", "cat:write", "mouse:write"}}
* )
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="type", type="string", length=32)
* @ORM\DiscriminatorMap({"dog" = "Dog", "cat" = "Cat", "mouse" = "Mouse"})
* @ORM\Entity(repositoryClass=AnimalRepository::class)
*/
abstract class Animal
{
/**
* @Groups({"animal:read"})
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @Groups({"animal:read", "animal:write"})
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @Groups({"animal:read", "animal:write"})
* @ORM\Column(type="string", length=255)
*/
private $sex;
/**
* @Groups({"animal:read", "animal:write"})
* @ORM\Column(type="integer")
* @ApiProperty(
* attributes={
* "openapi_context"={
* "example"=1000
* }
* }
* )
*/
private $weight;
/**
* @Groups({"animal:read", "animal:write"})
* @ORM\Column(type="date")
* @ApiProperty(
* attributes={
* "openapi_context"={
* "example"="2020/1/1"
* }
* }
* )
*/
private $birthday;
/**
* @Groups({"animal:read", "animal:write"})
* @ORM\Column(type="string", length=255)
*/
private $color;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSex(): ?string
{
return $this->sex;
}
public function setSex(string $sex): self
{
$this->sex = $sex;
return $this;
}
public function getWeight(): ?int
{
return $this->weight;
}
public function setWeight(int $weight): self
{
$this->weight = $weight;
return $this;
}
public function getBirthday(): ?\DateTimeInterface
{
return $this->birthday;
}
public function setBirthday(\DateTimeInterface $birthday): self
{
$this->birthday = $birthday;
return $this;
}
public function getColor(): ?string
{
return $this->color;
}
public function setColor(string $color): self
{
$this->color = $color;
return $this;
}
}
我本想遵循“一般情况下对休息的共同偏好,即使用单一终点/动物”,但理解您的理性“为/狗/猫/老鼠选择单独的终点/动物”。为了克服你们的原因,我还考虑了让动物具体化,并使用多态性的成分,这样动物就会有某种动物类型的对象。我想最终仍然需要学说继承来允许动物与这个对象有一对一的关系,但唯一的属性是PK ID和鉴别器。我可能会放弃这种追求
不确定我是否同意你不使用非规范化上下文的方法,但除非情况发生变化,我需要更多的灵活性,否则我将采用你的方法
我不明白你用这个标签。起初,我认为这是一个唯一的标识符,或者是一种暴露鉴别器的方法,但我不这么认为。请详细说明
关于“为了避免在每个具体子类中重复这些属性的定义,我使用yaml添加了一些组”,我的方法是为抽象动物类制作属性,而不是私有的,这样PHP可以使用反射,并在抽象动物和组“鼠标:读”中使用组“动物:读”,等等,并得到了我想要的结果
是的,请参见您关于限制列表与详细信息的结果的观点
我原本以为@MaxDepth
可以解决递归问题,但无法让它工作。然而,真正起作用的是使用@ApiProperty(readableLink=false)
我发现有些情况下,API平台生成的swagger规范在SwaggerUI中显示了anyOf
,但同意API平台似乎并不真正支持oneOf、allOf或anyOf。然而,不知何故,是否需要实现这一点?例如,动物ID在另一个表中,文档需要输入猫、狗或老鼠中的一个,不是吗?或者这一长长的类型列表是由序列化组的每个组合产生的吗?我认为在这个问题上没有可靠的来源,但我确实有,并且创建了,所以我将尝试自己回答您的问题
本教程旨在介绍大多数CRUD和搜索应用程序的共同点,包括api平台api和使用api平台客户端生成器生成的react客户端。本教程不涉及继承和多态性,因为我认为它不会出现在许多CRUD和搜索应用程序中,但它涉及很多方面,有关概述,请参阅中的章节列表。Api平台为这类应用程序的Api提供了许多现成的通用功能,只需要针对特定的资源和操作进行配置。在react分支中,这导致了重复出现的模式和重构到公共组件中,并最终导致教程附带的一个示例。这个答案中的序列化组方案更为通用,因为我对这个主题的理解随着时间的推移有所提高
您的类在Api平台2.6上是开箱即用的,不包括存储库类。我从注释中删除了它们,因为现在似乎没有调用它们的特定方法。您可以随时在需要时再次添加它们
与普遍偏好的REST相反
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use App\Repository\DogRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={"get", "post"},
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"dog:read"}},
* denormalizationContext={"groups"={"dog:write"}}
* )
* @ORM\Entity(repositoryClass=DogRepository::class)
*/
class Dog extends Animal
{
/**
* @ORM\Column(type="boolean")
* @Groups({"dog:read", "dog:write"})
*/
private $playsFetch;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"dog:read", "dog:write"})
* @ApiProperty(
* attributes={
* "openapi_context"={
* "example"="red"
* }
* }
* )
*/
private $doghouseColor;
/**
* #@ApiSubresource()
* @ORM\ManyToMany(targetEntity=Cat::class, mappedBy="dogsChasedBy")
* @MaxDepth(2)
* @Groups({"dog:read", "dog:write"})
*/
private $catsChased;
public function __construct()
{
$this->catsChased = new ArrayCollection();
}
public function getPlaysFetch(): ?bool
{
return $this->playsFetch;
}
public function setPlaysFetch(bool $playsFetch): self
{
$this->playsFetch = $playsFetch;
return $this;
}
public function getDoghouseColor(): ?string
{
return $this->doghouseColor;
}
public function setDoghouseColor(string $doghouseColor): self
{
$this->doghouseColor = $doghouseColor;
return $this;
}
/**
* @return Collection|Cat[]
*/
public function getCatsChased(): Collection
{
return $this->catsChased;
}
public function addCatsChased(Cat $catsChased): self
{
if (!$this->catsChased->contains($catsChased)) {
$this->catsChased[] = $catsChased;
$catsChased->addDogsChasedBy($this);
}
return $this;
}
public function removeCatsChased(Cat $catsChased): self
{
if ($this->catsChased->removeElement($catsChased)) {
$catsChased->removeDogsChasedBy($this);
}
return $this;
}
}
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use App\Repository\CatRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={"get", "post"},
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"cat:read"}},
* denormalizationContext={"groups"={"cat:write"}}
* )
* @ORM\Entity(repositoryClass=CatRepository::class)
*/
class Cat extends Animal
{
/**
* @ORM\Column(type="boolean")
* @Groups({"cat:read", "cat:write"})
*/
private $likesToPurr;
/**
* #@ApiSubresource()
* @ORM\OneToMany(targetEntity=Mouse::class, mappedBy="ateByCat")
* @MaxDepth(2)
* @Groups({"cat:read", "cat:write"})
*/
private $miceEaten;
/**
* #@ApiSubresource()
* @ORM\ManyToMany(targetEntity=Dog::class, inversedBy="catsChased")
* @MaxDepth(2)
* @Groups({"cat:read", "cat:write"})
*/
private $dogsChasedBy;
public function __construct()
{
$this->miceEaten = new ArrayCollection();
$this->dogsChasedBy = new ArrayCollection();
}
public function getLikesToPurr(): ?bool
{
return $this->likesToPurr;
}
public function setLikesToPurr(bool $likesToPurr): self
{
$this->likesToPurr = $likesToPurr;
return $this;
}
/**
* @return Collection|Mouse[]
*/
public function getMiceEaten(): Collection
{
return $this->miceEaten;
}
public function addMiceEaten(Mouse $miceEaten): self
{
if (!$this->miceEaten->contains($miceEaten)) {
$this->miceEaten[] = $miceEaten;
$miceEaten->setAteByCat($this);
}
return $this;
}
public function removeMiceEaten(Mouse $miceEaten): self
{
if ($this->miceEaten->removeElement($miceEaten)) {
// set the owning side to null (unless already changed)
if ($miceEaten->getAteByCat() === $this) {
$miceEaten->setAteByCat(null);
}
}
return $this;
}
/**
* @return Collection|Dog[]
*/
public function getDogsChasedBy(): Collection
{
return $this->dogsChasedBy;
}
public function addDogsChasedBy(Dog $dogsChasedBy): self
{
if (!$this->dogsChasedBy->contains($dogsChasedBy)) {
$this->dogsChasedBy[] = $dogsChasedBy;
}
return $this;
}
public function removeDogsChasedBy(Dog $dogsChasedBy): self
{
$this->dogsChasedBy->removeElement($dogsChasedBy);
return $this;
}
}
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use App\Repository\MouseRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={"get", "post"},
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"mouse:read"}},
* denormalizationContext={"groups"={"mouse:write"}}
* )
* @ORM\Entity(repositoryClass=MouseRepository::class)
*/
class Mouse extends Animal
{
/**
* @ORM\Column(type="boolean")
* @Groups({"mouse:read", "mouse:write"})
*/
private $likesCheese;
/**
* #@ApiSubresource()
* @ORM\ManyToOne(targetEntity=Cat::class, inversedBy="miceEaten")
* @MaxDepth(2)
* @Groups({"mouse:read", "mouse:write"})
*/
private $ateByCat;
public function getLikesCheese(): ?bool
{
return $this->likesCheese;
}
public function setLikesCheese(bool $likesCheese): self
{
$this->likesCheese = $likesCheese;
return $this;
}
public function getAteByCat(): ?Cat
{
return $this->ateByCat;
}
public function setAteByCat(?Cat $ateByCat): self
{
$this->ateByCat = $ateByCat;
return $this;
}
}
class AnimalRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry, ?string $class=null)
{
parent::__construct($registry, $class??Animal::class);
}
}
class DogRepository extends AnimalRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Dog::class);
}
}
// Cat and Mouse Repository similar
{
"@context": "/contexts/Cat",
"@id": "/cats/1",
"@type": "Cat",
"likesToPurr": true,
"miceEaten": [
{
"@id": "/mice/3",
"@type": "Mouse",
"label": "2021-01-13"
}
],
"dogsChasedBy": [
{
"@id": "/dogs/2",
"@type": "Dog",
"label": "Bella"
}
],
"name": "Felix",
"sex": "m",
"weight": 12,
"birthday": "2020-03-13T00:00:00+00:00",
"color": "grey",
"label": "Felix"
}
serializer:
mapping:
paths: ['%kernel.project_dir%/config/serialization']
{
"@context": "/contexts/Mouse",
"@id": "/mice",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/mice/3",
"@type": "Mouse",
"ateByCat": {
"@id": "/cats/1",
"@type": "Cat",
"label": "Felix"
},
"label": "2021-01-13",
"name": "mimi",
"birthday": "2021-01-13T00:00:00+00:00",
"color": "grey"
}
],
"hydra:totalItems": 1
}
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"cat:list", "dog:list", "mouse:list", "related"}}
* },
* },
{
"@context": "/contexts/Animal",
"@id": "/animals",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/cats/1",
"@type": "Cat",
"likesToPurr": true,
"name": "Felix",
"birthday": "2020-03-13T00:00:00+00:00",
"color": "grey",
"label": "Felix"
},
{
"@id": "/dogs/2",
"@type": "Dog",
"playsFetch": true,
"name": "Bella",
"birthday": "2019-03-13T00:00:00+00:00",
"color": "brown",
"label": "Bella"
},
{
"@id": "/mice/3",
"@type": "Mouse",
"ateByCat": {
"@id": "/cats/1",
"@type": "Cat",
"likesToPurr": true,
"name": "Felix",
"birthday": "2020-03-13T00:00:00+00:00",
"color": "grey",
"label": "Felix"
},
"label": "2021-01-13",
"name": "mimi",
"birthday": "2021-01-13T00:00:00+00:00",
"color": "grey"
}
],
"hydra:totalItems": 3
}
{
"@context": "/contexts/Animal",
"@id": "/animals",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/cats/1",
"@type": "Cat",
"name": "Felix",
"color": "grey",
"label": "Felix"
},
{
"@id": "/dogs/2",
"@type": "Dog",
"name": "Bella",
"color": "brown",
"label": "Bella"
},
{
"@id": "/mice/3",
"@type": "Mouse",
"ateByCat": {
"@id": "/cats/1",
"@type": "Cat",
"name": "Felix",
"color": "grey",
"label": "Felix"
},
"label": "2021-01-13",
"name": "mimi",
"color": "grey"
}
],
"hydra:totalItems": 3
}
Animal-animal.list_related
Animal.jsonld-animal.list_related
Cat
Cat-cat.list_related
Cat-cat.read_cat.list_related
Cat-dog.read_dog.list_related
Cat-mouse.list_related
Cat-mouse.read_mouse.list_related
Cat.jsonld
Cat.jsonld-cat.list_related
Cat.jsonld-cat.read_cat.list_related
Cat.jsonld-dog.read_dog.list_related
Cat.jsonld-mouse.list_related
Cat.jsonld-mouse.read_mouse.list_related
Dog
Dog-cat.read_cat.list_related
Dog-dog.list_related
Dog-dog.read_dog.list_related
Dog.jsonld
Dog.jsonld-cat.read_cat.list_related
Dog.jsonld-dog.list_related
Dog.jsonld-dog.read_dog.list_related
Greeting
Greeting.jsonld
Mouse
Mouse-cat.read_cat.list_related
Mouse-mouse.list_related
Mouse-mouse.read_mouse.list_related
Mouse.jsonld
Mouse.jsonld-cat.read_cat.list_related
Mouse.jsonld-mouse.list_related
Mouse.jsonld-mouse.read_mouse.list_related
<?php
// api/src/Entity/Animal.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"animal:list", "related"}}
* },
* },
* itemOperations={},
* )
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="type", type="string", length=32)
* @ORM\DiscriminatorMap({"dog" = "Dog", "cat" = "Cat", "mouse" = "Mouse"})
* @ORM\Entity()
*/
abstract class Animal
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"animal:list"})
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
*/
private $sex;
/**
* @ORM\Column(type="integer")
* @ApiProperty(
* attributes={
* "openapi_context"={
* "example"=1000
* }
* }
* )
*/
private $weight;
/**
* @ORM\Column(type="date")
* @ApiProperty(
* attributes={
* "openapi_context"={
* "example"="2020/1/1"
* }
* }
* )
*/
private $birthday;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"animal:list"})
*/
private $color;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSex(): ?string
{
return $this->sex;
}
public function setSex(string $sex): self
{
$this->sex = $sex;
return $this;
}
public function getWeight(): ?int
{
return $this->weight;
}
public function setWeight(int $weight): self
{
$this->weight = $weight;
return $this;
}
public function getBirthday(): ?\DateTimeInterface
{
return $this->birthday;
}
public function setBirthday(\DateTimeInterface $birthday): self
{
$this->birthday = $birthday;
return $this;
}
public function getColor(): ?string
{
return $this->color;
}
public function setColor(string $color): self
{
$this->color = $color;
return $this;
}
/**
* Represent the entity to the user in a single string
* @return string
* @ApiProperty(iri="http://schema.org/name")
* @Groups({"related"})
*/
function getLabel() {
return $this->getName();
}
}
<?php
// api/src/Entity/Cat.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"cat:list", "related"}}
* },
* "post"
* },
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"cat:read", "cat:list", "related"}}
* )
* @ORM\Entity()
*/
class Cat extends Animal
{
/**
* @ORM\Column(type="boolean")
* @Groups({"cat:list"})
*/
private $likesToPurr;
/**
* #@ApiSubresource()
* @ORM\OneToMany(targetEntity=Mouse::class, mappedBy="ateByCat")
* @MaxDepth(2)
* @Groups({"cat:read"})
*/
private $miceEaten;
/**
* #@ApiSubresource()
* @ORM\ManyToMany(targetEntity=Dog::class, inversedBy="catsChased")
* @MaxDepth(2)
* @Groups({"cat:read"})
*/
private $dogsChasedBy;
public function __construct()
{
$this->miceEaten = new ArrayCollection();
$this->dogsChasedBy = new ArrayCollection();
}
public function getLikesToPurr(): ?bool
{
return $this->likesToPurr;
}
public function setLikesToPurr(bool $likesToPurr): self
{
$this->likesToPurr = $likesToPurr;
return $this;
}
/**
* @return Collection|Mouse[]
*/
public function getMiceEaten(): Collection
{
return $this->miceEaten;
}
public function addMiceEaten(Mouse $miceEaten): self
{
if (!$this->miceEaten->contains($miceEaten)) {
$this->miceEaten[] = $miceEaten;
$miceEaten->setAteByCat($this);
}
return $this;
}
public function removeMiceEaten(Mouse $miceEaten): self
{
if ($this->miceEaten->removeElement($miceEaten)) {
// set the owning side to null (unless already changed)
if ($miceEaten->getAteByCat() === $this) {
$miceEaten->setAteByCat(null);
}
}
return $this;
}
/**
* @return Collection|Dog[]
*/
public function getDogsChasedBy(): Collection
{
return $this->dogsChasedBy;
}
public function addDogsChasedBy(Dog $dogsChasedBy): self
{
if (!$this->dogsChasedBy->contains($dogsChasedBy)) {
$this->dogsChasedBy[] = $dogsChasedBy;
}
return $this;
}
public function removeDogsChasedBy(Dog $dogsChasedBy): self
{
$this->dogsChasedBy->removeElement($dogsChasedBy);
return $this;
}
}
<?php
// api/src/Entity/Dog.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"dog:list", "related"}}
* },
* "post"
* },
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"dog:read", "dog:list", "related"}},
* )
* @ORM\Entity()
*/
class Dog extends Animal
{
/**
* @ORM\Column(type="boolean")
* @Groups({"dog:list"})
*/
private $playsFetch;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"dog:read"})
* @ApiProperty(
* attributes={
* "openapi_context"={
* "example"="red"
* }
* }
* )
*/
private $doghouseColor;
/**
* #@ApiSubresource()
* @ORM\ManyToMany(targetEntity=Cat::class, mappedBy="dogsChasedBy")
* @MaxDepth(2)
* @Groups({"dog:read"})
*/
private $catsChased;
public function __construct()
{
$this->catsChased = new ArrayCollection();
}
public function getPlaysFetch(): ?bool
{
return $this->playsFetch;
}
public function setPlaysFetch(bool $playsFetch): self
{
$this->playsFetch = $playsFetch;
return $this;
}
public function getDoghouseColor(): ?string
{
return $this->doghouseColor;
}
public function setDoghouseColor(string $doghouseColor): self
{
$this->doghouseColor = $doghouseColor;
return $this;
}
/**
* @return Collection|Cat[]
*/
public function getCatsChased(): Collection
{
return $this->catsChased;
}
public function addCatsChased(Cat $catsChased): self
{
if (!$this->catsChased->contains($catsChased)) {
$this->catsChased[] = $catsChased;
$catsChased->addDogsChasedBy($this);
}
return $this;
}
public function removeCatsChased(Cat $catsChased): self
{
if ($this->catsChased->removeElement($catsChased)) {
$catsChased->removeDogsChasedBy($this);
}
return $this;
}
}
<?php
// api/src/Entity/Mouse.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"mouse:list", "related"}}
* },
* "post"
* },
* itemOperations={"get", "put", "patch", "delete"},
* normalizationContext={"groups"={"mouse:read", "mouse:list", "related"}},
* )
* @ORM\Entity()
*/
class Mouse extends Animal
{
/**
* @ORM\Column(type="boolean")
* @Groups({"mouse:read"})
*/
private $likesCheese;
/**
* #@ApiSubresource()
* @ORM\ManyToOne(targetEntity=Cat::class, inversedBy="miceEaten")
* @MaxDepth(2)
* @Groups({"mouse:list", "animal:list"})
*/
private $ateByCat;
public function getLikesCheese(): ?bool
{
return $this->likesCheese;
}
public function setLikesCheese(bool $likesCheese): self
{
$this->likesCheese = $likesCheese;
return $this;
}
public function getAteByCat(): ?Cat
{
return $this->ateByCat;
}
public function setAteByCat(?Cat $ateByCat): self
{
$this->ateByCat = $ateByCat;
return $this;
}
/**
* Represent the entity to the user in a single string
* @return string
* @ApiProperty(iri="http://schema.org/name")
* @Groups({"related"})
*/
function getLabel() {
return $this->getBirthday()->format('Y-m-d');
}
}
# api/config/serialization/Cat.yaml
App\Entity\Cat:
attributes:
name:
groups: ['cat:list']
sex:
groups: ['cat:read']
weight:
groups: ['cat:read']
birthday:
groups: ['cat:list']
color:
groups: ['cat:list']
# api/config/serialization/Dog.yaml
App\Entity\Dog:
attributes:
name:
groups: ['dog:list']
sex:
groups: ['dog:read']
weight:
groups: ['dog:read']
birthday:
groups: ['dog:list']
color:
groups: ['dog:list']
# api/config/serialization/Mouse.yaml
App\Entity\Mouse:
attributes:
name:
groups: ['mouse:list']
sex:
groups: ['mouse:read']
weight:
groups: ['mouse:read']
birthday:
groups: ['mouse:list']
color:
groups: ['mouse:list']