Bonjour,
Désolé de vous déranger pour cela, mais je suis en train de suivre votre cours pour créer une API REST sous Symfony 3, et j’ai un soucis lorsque j’essaie de sérializer mes objets pour éviter les références circulaires comme vous expliquez dans votre cours.
Je m’explique, j’ai 2 entités : Project et Idea avec une relation OneToMany (entité propriétaire Project), un peu avec le même principe que vous donnez dans votre cours avec les deux entités Place et Price.
J’ai bien créé les deux fichiers yml :
src/AppBundle/Resources/config/validation.yml
1 2 3 4 5 | AppBundle\Entity\Idea: properties: tag: - NotBlank: ~ - Type: string |
src/AppBundle/Resources/config/serialization.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | AppBundle\Entity\Project: attributes: id: groups: ['project', 'idea'] name: groups: ['project', 'idea'] description: groups: ['project', 'idea'] theme: groups: ['project', 'idea'] public: groups: ['project', 'idea'] ideas: groups: ['project'] AppBundle\Entity\Idea: attributes: id: groups: ['project', 'idea'] tag: groups: ['project', 'idea'] project: groups: ['idea'] |
Mes 2 controllers :
src/AppBundle/Controller/Project/IdeaController
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 | <?php namespace AppBundle\Controller\Project; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use FOS\RestBundle\Controller\Annotations as Rest; // alias pour toutes les annotations use AppBundle\Form\Type\IdeaType; use AppBundle\Entity\Idea; class IdeaController extends Controller { /** * @Rest\View(serializerGroups={"idea"}) * @Rest\Get("/projects/{id}/ideas") */ public function getIdeasAction(Request $request) { $project = $this->get('doctrine.orm.entity_manager') ->getRepository('AppBundle:Project') ->find($request->get('id')); // L'identifiant en tant que paramétre n'est plus nécessaire /* @var $project Project */ if (empty($project)) { return $this->projectNotFound(); } return $project->getIdea(); } /** * @Rest\View(statusCode=Response::HTTP_CREATED,serializerGroups={"idea"}) * @Rest\Post("/projects/{id}/ideas") */ public function postIdeasAction(Request $request) { $project = $this->get('doctrine.orm.entity_manager') ->getRepository('AppBundle:Project') ->find($request->get('id')); /* @var $project Project */ if (empty($project)) { return $this->projectNotFound(); } $idea = new Idea(); $idea->setProject($project); // Ici, le projet est associé à l'idée $form = $this->createForm(IdeaType::class, $idea); // Le paramétre false dit à Symfony de garder les valeurs dans notre // entité si l'utilisateur n'en fournit pas une dans sa requête $form->submit($request->request->all()); if ($form->isValid()) { $em = $this->get('doctrine.orm.entity_manager'); $em->persist($idea); $em->flush(); return $idea; } else { return $form; } } private function projectNotFound() { return \FOS\RestBundle\View\View::create(['message' => 'Project not found'], Response::HTTP_NOT_FOUND); } } |
src/AppBundle/Controller/ProjectController
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 | <?php namespace AppBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use FOS\RestBundle\Controller\Annotations\Get; use FOS\RestBundle\Controller\Annotations as Rest; // alias pour toutes les annotations use AppBundle\Form\Type\ProjectType; use AppBundle\Entity\Project; class ProjectController extends Controller { /** * @Rest\View() * @Rest\Get("/projects") */ public function getProjectsAction(Request $request) { $project = $this->get('doctrine.orm.entity_manager') ->getRepository('AppBundle:Project') ->findAll(); /* @var $projects Project[] */ return $project; } /** * @Rest\View() * @Rest\Get("/projects/{id}") */ public function getProjectAction(Request $request) { $project = $this->get('doctrine.orm.entity_manager') ->getRepository('AppBundle:Project') ->find($request->get('id')); // L'identifiant en tant que paramétre n'est plus nécessaire /* @var $project Project */ if (empty($project)) { return \FOS\RestBundle\View\View::create(['message' => 'Project not found'], Response::HTTP_NOT_FOUND); } return $project; } /** * @Rest\View(statusCode=Response::HTTP_CREATED) * @Rest\Post("/projects") */ public function postProjectsAction(Request $request) { $project = new Project(); $form = $this->createForm(ProjectType::class, $project); $form->submit($request->request->all()); // Validation des données if ($form->isValid()) { $em = $this->get('doctrine.orm.entity_manager'); $em->persist($project); $em->flush(); return $project; } else { return $form; } } /** * @Rest\View(statusCode=Response::HTTP_NO_CONTENT) * @Rest\Delete("/projects/{id}") */ public function removeProjectAction(Request $request) { $em = $this->get('doctrine.orm.entity_manager'); $project = $em->getRepository('AppBundle:Project') ->find($request->get('id')); /* @var $project Project */ if ($project) { $em->remove($project); $em->flush(); } } /** * @Rest\View() * @Rest\Put("/projects/{id}") */ public function updateProjectAction(Request $request) { return $this->updateProject($request, true); } /** * @Rest\View() * @Rest\Patch("/projects/{id}") */ public function patchProjectAction(Request $request) { return $this->updateProject($request, false); } private function updateProject(Request $request, $clearMissing) { $project = $this->get('doctrine.orm.entity_manager') ->getRepository('AppBundle:Project') ->find($request->get('id')); // L'identifiant en tant que paramètre n'est plus nécessaire /* @var $project Project */ if (empty($project)) { return \FOS\RestBundle\View\View::create(['message' => 'Project not found'], Response::HTTP_NOT_FOUND); } $form = $this->createForm(ProjectType::class, $project); // Le paramètre false dit à Symfony de garder les valeurs dans notre // entité si l'utilisateur n'en fournit pas une dans sa requête $form->submit($request->request->all(), $clearMissing); if ($form->isValid()) { $em = $this->get('doctrine.orm.entity_manager'); $em->persist($project); $em->flush(); return $project; } else { return $form; } } } |
Lorsque que j’essaie de récupérer tout les idées par exemple du projet 1, j’obtiens un fichier JSON vide… (mais je n’ai plus de références circulaires)
Lorsqu’avec PostMan je fais un GET de : http://localhost/rest_api_popidea/web/app_dev.php/projects/1/ideas
J’obtiens dans mon fichier JSON :
[ [], [], [], [] ]
Je vois bien qu’il y a 4 idées dans le projet 1, mais ils sont vides..
J’ai l’impression que mes deux fichiers :
src/AppBundle/Resources/config/validation.yml
src/AppBundle/Resources/config/serialization.yml
ne sont pas pris en compte (chargés) par Symfony.
Je pense avoir oublié une déclaration mais je ne sais pas où…?
Merci le temps accordé. Et merci pour votre super tutoriel au passage !
Jonathan