Symfony/FosRestBundle et relation entre entité

a marqué ce sujet comme résolu.

Bonjour,

Je vous remercie pour votre excellent tutoriel sur l’API Rest de Symfony ! Cependant j’ai une question car je me retrouve bloqué en voulant POST une entity qui possède une relation ManyToOne vers une autre entity.

Pour résumer, je dispose de 2 entity : "Annonce" et "Localisation". Une "Annonce" possède une relation ManyToOne vers une "Localisation". La table "localisation" contient des données de référence avec le nom des villes, code postaux, etc. Côté UI, lorsque je crée une nouvelle annonce, je récupère via un autocomplete mon objet "Localisation". Lorsque je soumets mon formulaire j’ai un objet sérialisé qui ressemble à :{ title: 'Mon annonce', description: 'Ma description', location: { id: 10, city: 'Ma ville' }}

Lorsque je récupère le body de ma requête, tout les éléments sont présents. Cependant le FormBuilder ne parvient à déserialiser l’objet. Dans le AnnonceType.php :builder->add(...)->add('location', LocationType::class)

Cependant l’attribut ’location’ de l’objet désérialisé est toujours null.

Avez-vous une idée ?

Salut,

Il existe un cookbook dans la documentation officielle de Symfony pour gérer les formulaires imbriqués (http://symfony.com/doc/current/form/embedded.html).

Pourrais-tu rajouter le code de tes deux formulaires (LocationType et l’annonce) ?

Salut,

Merci pour le lien, j’ai été sur la documentation de Symfony pour tester différentes façons mais je n’ai rien trouvé de fonctionnel.

GearAdvertisementType.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
class GearAdvertisementType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('description')
            ->add('price')
            ->add('location', EntityType::class, array(
                'class' => 'AppBundle:Location'
            ));
            //->add('location', LocationType::class);
    }

`

Et le LocationType.php :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
class LocationType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            //->add('id')
            ->add('city')
            ->add('postalCode')
            ->add('gpsCoordinates');
    }

Les commentaires portent à propos de ce que j’ai pu essayer. Je pense que le problème vient du fait que je possède déjà un id pour Location.

+0 -0

L’EntityType étend la classe ChoiceType de Symfony. Dans l’attribut location, tu ne peux pas mettre un objet mais plutôt son identifiant.

Avec un formulaire classique le payload devrait ressembler à :

1
{ title: 'Mon annonce', description: 'Ma description', location: 10}

Mais avec REST, personnellement je n’utiliserais pas cette technique.

Les commentaires portent à propos de ce que j’ai pu essayer. Je pense que le problème vient du fait que je possède déjà un id pour Location.

Donc tu ajoutes un commentaire à une location. Je partirais plus sur :

1
POST /locations/{id_de_location}/comments

Payload:

1
{ title: 'Mon annonce', description: 'Ma description'}

Dans mon contrôleur ou mon service, je lis le commentaire à la location manuellement. Dans le cours c’est comme dans la relation entre Place et Price

Merci, j’ai pensé à cette solution mais cela ne posera pas problème lorsqu’une annonce dépendra d’une catégorie, sous-catégorie, type, etc. ?
Je peux me retrouver avec une route :
POST /location/{location_id}/category/{category_id}/type/{type_id}/...

Côté FO, j’utilise TypeScript et mes DTO sont identiques à mes Entities, par conséquent il me sera plus pratique de poster l’objet complet plutôt que décomposé comme dans l’exemple. Est-ce la seule solution ?

EDIT: En parlant de commentaires, je parlais du code commenté, pas d’ajouter des commentaires. J’aurais du préciser.

+0 -0

Est-ce la seule solution ?

D’un point de vue purement REST, ça serait la meilleure solution. Tu postes l’objet complet alors qu’en réalité, il n’y a que son identifiant qui t’intéresse.

Mais les formulaires imbriqués pourraient aussi faire l’affaire (mais ça sera très moche). Il faudra le coupler avec les data transformers.

En optant pour la solution REST, je vais récupérer mon Annonce via le Payload et construire mon Entity à partir du FormBuilder.
Pour lier mon location_id à mon Annonce, je génère une référence de Location avec EntityManager en lui passant location_id en paramètre ? C’est peut-être mieux que de récupérer l’objet ?

Pour la validation de mon paramètre location_id, quel est le plus intéressant ?

Le lien vers le cours Place et Price me retourne une 403, mais j’ai retrouvé de quel passage il s’agissait.

En optant pour la solution REST, je vais récupérer mon Annonce via le Payload et construire mon Entity à partir du FormBuilder. Pour lier mon location_id à mon Annonce, je génère une référence de Location avec EntityManager en lui passant location_id en paramètre ? C’est peut-être mieux que de récupérer l’objet ?

L’idéal serait de le récupérer de la base de données. Tu pourras ainsi vérifier qu’il existe et rajouter d’autres contraintes si besoin.

Pour la validation de mon paramètre location_id, quel est le plus intéressant ?

Normalement seul son existence est important. En le récupérant depuis ta base de données, tu en auras la preuve.

Le lien vers le cours Place et Price me retourne une 403, mais j’ai retrouvé de quel passage il s’agissait.

J’ai édité mon post. J’avais mis le lien du cours pour l’édition ^^ .

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

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