Bonjour,
A partir d'un controller de mon API, je cherche à renvoyer une liste d'éléments.
Ces éléments sont des objets sérialisés en JSON.
Y'a t-il un moyen natif au Serializer pour faire cela directement plutôt que de construire à la main un JSON qui contient ma liste de plusieurs JSON?
J'éspère me faire comprendre... voici mon code.
"```"
[Route('/product/list/custom', name: 'product_list')]public function productsList(ProductRepository $rep, SerializerService $serializerService):Response
{
$pdt_liste = $rep->findAll();
$datas = "{";
$i = 1;
foreach ($pdt_liste as $pdt)
{
$serializer = $serializerService->getSerializer();
$pdtJson = $serializer->serialize(
$pdt,
'json',
[
AbstractNormalizer::IGNORED_ATTRIBUTES => ['products','prices']
]
);
$datas .= '"'.$i.'": '.$pdtJson.",";
$i++;
}
$datas = substr($datas,0,-1);
$datas .= "}";
return new Response($datas) ;
}
"```"
Je précise que j'ai utilisé un Serializer car dans ma liste de 'pdt' il y a une relation avec une table 'marque' et que sans ça je n'ai pas l'objet 'marque' hydraté complétement , je ne récupèrais que l'ID de 'marque'.
Merci.
Bonjour,
Si ton controleur étend AbstractController (ce qui est le cas par défaut), il y a une méthode json() donc tu peux faire :
return $this->json($pdt_liste);
Merci pour la réponse.
Alors en effet je l'avais utilisée mais comme je le précise à la fin de mon message, avec cette méthode mon objet 'marque' qui est une relation de la table 'product' n'est pas hydraté correctement.
Voici ce que me renvoie la méthode $this->json
"" "marque":"\/api\/marques\/1" "
"
Alors que moi j'attends ça:
"" "marque":{"id":1,"marqueNom":"adidas","marqueCode":0 "
"
Oui, il faut utiliser les groupes de serialisation en mettant des annotations dans tes entités avec les annotations @Groups.
Il faut mettre l'annotation dans l'objet product et dans l'objet marque sinon le serializer ne prend que l'id des entités liées.
:) je m'y attendais.
J'ai deséspèrement essayer de faire ça hier mais j'avais un pb de référence circulaire.
Je n'ai probablement pas compris où mettre ces annotations.
Si tu as une voie sur laquelle me lancer, je suis preneur.
Dans la class 'PRODUCT' ça serait un truc du genre:
"" [ORM\ManyToOne(targetEntity: Marque::class, inversedBy: 'products')] [ORM\JoinColumn(nullable: false)] [Groups(['testmarque'])] private $marque; "
"
Et dans la class 'MARQUE', idem:
"" [ORM\OneToMany(mappedBy: 'marque', targetEntity: Product::class)] [Groups(['testmarque'])] private $products; "
"
J'vais tenté de m'y recoller.
Merci
edit: désolé j'ai un souci de mise en forme avec la syntaxe des annotations
La référence circulaire, c'est parceque tu as une liaison qui boucle entre tes deux entités, il faut donc lui préciser un peu les choses.
J'ai fait un petit exemple rapidement :
Voici les champs de la classe Product :
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['product:read'])]
private $id;
#[ORM\Column(type: 'string', length: 255)]
#[Groups(['product:read'])]
private $nom;
#[ORM\Column(type: 'float')]
#[Groups(['product:read'])]
private $prix;
#[ORM\ManyToOne(targetEntity: Marque::class, inversedBy: 'products')]
#[ORM\JoinColumn(nullable: false)]
#[Groups(['product:read'])]
private $marque;
Et ceux de la classe Marque :
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['product:read'])]
private $id;
#[ORM\Column(type: 'string', length: 255)]
#[Groups(['product:read'])]
private $nom;
#[ORM\Column(type: 'string', length: 255)]
#[Groups(['product:read'])]
private $code;
#[ORM\OneToMany(mappedBy: 'marque', targetEntity: Product::class)]
private $products;
Tu peux voir que j'ai mis le groupe 'product:read' sur les champs que je veux afficher mais pas sur le champ qui fait la relation sinon ça boucle.
Et pour utiliser ça dans le controleur, je précise au serializer quel groupe je demande :
$products = .... // récupération des products
return $this->json(
$products,
200,
[],
['groups' => 'product:read']
);
un grand merci à toi.
C'est exactement ce que je cherchais.
Du coup plus d''interêt (pour moi) d'utiliser un Serializer pour l'instant.
Merci