2 pièce(s) jointe(s)
API Platform - Retour incomplet pour une entité self-reference
Bonjour à tous,
Je débute sur API Platform et j'éprouve des difficultés à obtenir le retour de données que je voudrais.
CONTEXTE:
Je suis en train de créer une petite application qui a pour but de gérer un stock.
Un utilisateurs peut enregistrer des produits et des catégories liées à ces derniers.
PROBLEMATIQUE:
J'aimerais pouvoir faire une requête HTTP afin d'obtenir toutes les catégories et sous-catégories appartenant à l'utilisateur courant.
Mon entité User est lié à l'entité Category en OneToMany.
L'entité Category a une référence interne afin de pouvoir créer des sous-catégories.
Dans mon entité User, j'ai ajouté l'instruction @ApiSubresource() sur le champs categories.
Lorsque j'appelle la route suivante:
Pièce jointe 520634
J'obtiens le retour suivant:
Pièce jointe 520637
Dans le retour, pour les champs children, à la place des routes des ressources, j'aimerais obtenir les ressources elle-mêmes.
C'est à dire la liste des sous-catégories avec id et name.
Après avoir lu la doc, j'ai essayé en travaillant sur les groupe de normalisation, mais le résultat est resté identique.
J'ai également ajouté @ApiSubresource() sur le champ children de mon entité Catégorie mais rien n'a changé.
- Entité User
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
|
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use ApiPlatform\Core\Annotation\ApiResource;
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @UniqueEntity("email")
* @ApiResource()
*/
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=180, unique=true)
* @Assert\NotBlank
* @Assert\Email
*/
private $email;
/**
* @ORM\Column(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string")
* @Assert\NotBlank
* @Assert\Length(
* min = 6,
* minMessage = "The password must be at least 6 characters."
* )
*/
private $password;
/**
* @var string
* @Assert\IdenticalTo(
* propertyPath="password",
* message="This value should be identical to password")
*
*/
private $passwordConfirmation;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Assert\Type("string")
*/
private $firstName;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Assert\Type("string")
*/
private $lastName;
/**
* @ORM\Column(type="date", nullable=true)
*/
private $birthdate;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Category", mappedBy="user")
* @ApiSubresource()
*/
private $categories;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Product", mappedBy="user")
*/
private $products;
public function __construct()
{
$this->categories = new ArrayCollection();
$this->products = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @return string
*/
public function getPasswordConfirmation(): string
{
return $this->passwordConfirmation;
}
/**
* @param string $passwordConfirmation
*/
public function setPasswordConfirmation(string $passwordConfirmation): void
{
$this->passwordConfirmation = $passwordConfirmation;
}
/**
* @see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getBirthdate(): ?\DateTimeInterface
{
return $this->birthdate;
}
public function setBirthdate(?\DateTimeInterface $birthdate): self
{
$this->birthdate = $birthdate;
return $this;
}
/**
* @return Collection|Category[]
*/
public function getCategories(): Collection
{
return $this->categories;
}
public function addCategory(Category $category): self
{
if (!$this->categories->contains($category)) {
$this->categories[] = $category;
$category->setUser($this);
}
return $this;
}
public function removeCategory(Category $category): self
{
if ($this->categories->contains($category)) {
$this->categories->removeElement($category);
// set the owning side to null (unless already changed)
if ($category->getUser() === $this) {
$category->setUser(null);
}
}
return $this;
}
/**
* @return Collection|Product[]
*/
public function getProducts(): Collection
{
return $this->products;
}
public function addProduct(Product $product): self
{
if (!$this->products->contains($product)) {
$this->products[] = $product;
$product->setUser($this);
}
return $this;
}
public function removeProduct(Product $product): self
{
if ($this->products->contains($product)) {
$this->products->removeElement($product);
// set the owning side to null (unless already changed)
if ($product->getUser() === $this) {
$product->setUser(null);
}
}
return $this;
}
} |
- Entité Category
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity(repositoryClass="App\Repository\CategoryRepository")
* @ApiResource()
*/
class Category
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="categories")
* @ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Product", mappedBy="category")
*/
private $products;
/**
* @OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
/**
* @ManyToOne(targetEntity="Category", inversedBy="children")
*/
private $parent;
public function __construct()
{
$this->products = new ArrayCollection();
$this->children = new ArrayCollection();
}
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 getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
/**
* @return Collection|Product[]
*/
public function getProducts(): Collection
{
return $this->products;
}
public function addProduct(Product $product): self
{
if (!$this->products->contains($product)) {
$this->products[] = $product;
$product->setCategory($this);
}
return $this;
}
public function removeProduct(Product $product): self
{
if ($this->products->contains($product)) {
$this->products->removeElement($product);
// set the owning side to null (unless already changed)
if ($product->getCategory() === $this) {
$product->setCategory(null);
}
}
return $this;
}
/**
* @return mixed
*/
public function getChildren()
{
return $this->children;
}
/**
* @param mixed $children
*/
public function setChildren($children): void
{
$this->children [] = $children;
}
/**
* @return mixed
*/
public function getParent()
{
return $this->parent;
}
/**
* @param mixed $parent
*/
public function setParent($parent): void
{
$this->parent = $parent;
}
} |
Je cherche à comprendre comment est il possible d'obtenir le retour souhaité à travers une entité lié en ManyToOne et ayant une self-référence.
Merci pour votre aide ;)