Problème serialization.yml et références circulaires

Symfony 3 - Suivi du tuto de Zeste de savoir

a marqué ce sujet comme résolu.
Auteur du sujet

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

Édité par BlueJohn

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte