Renvoyer un id plutôt qu'un sous-objet

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Dans le cadre du développement de mon API Rest sous Symfony 3, lorsque l'on fait un get sur une ressource je renvoie l'objet désirer.

Le problème étant que cet objet contient des référence vers des sous objet et eux-même pouvant faire référence à de sous objet.

Je voudrai pour les éléments que je souhaite (donc non basé sur la profondeur) pouvoir dire que je ne souhaite pas l'objet en tant que tel mais uniquement son identifiant, idéalement un comportement similaire au @Groups afin de pouvoir filtrer en fonction du contexte.

Pour illustrer:

1
2
3
4
5
6
7
8
<?php
Class Test {
    /**
     * @var Fille
     * @Serializer\ShowId({"groups"})
     */
    $fille;
}

Et que cela affiche style:

1
2
3
{
  "fille": 5
}

plutôt que:

1
2
3
4
5
{
  "fille": {
    "id": 5, "foo": "bar"
  }
}

Y-a-t'il moyen d'arriver au résultat désirer ?

Merci d'avance pour votre aide.
Cordialement, La source.

+0 -0

Salut La source,

Avant de te proposer des solutions, je pense que renvoyer un même attribut qui un coup désigne un objet et un autre un identifiant peut facilement induire en erreur.

En utilisant les groupes, tu pourrais configurer un groupe qui n'affiche que l'identifiant et t'aurais quelque chose du style :

1
2
3
4
5
{
  "fille": {
    "id": 5
  }
}

Tu auras ainsi un format simple avec l'id seul et un format détaillé avec tout ce que tu veux dedans en plus de l'id.

Une autre solution consisterait à mettre une méthode getFilleId dans ton entité qui renvoie l'identifiant et l'associer à un groupe particulier. Lorsque Symfony va sérialiser l'entité, tu auras un attribut qui s'appelle filleId.

Sinon, si ton objectif c'est d'avoir impérativement le comportement que tu décris, je pense qu'il va falloir que tu installes JMSSerializerBundle (j'ai un chapitre dessus, mais il n'est pas encore publié).

Avec JMSSerializerBundle, tu peux utiliser la notion de propriétés virtuelles.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
AppBundle\Entity\MaClasse:
    exclusion_policy: none
    properties:
        id:
            groups: ['groupe-sans-id', 'groupe-id']
        value:
            groups: ['groupe-sans-id', 'groupe-id']
        fille:
            groups: ['groupe-sans-id']
    virtual_properties:
        getFilleId :
            serialized_name: fille
            type: integer
            groups: ['groupe-id']

getFilleId est une méthode qui renvoie l'identifiant de la classe fille. Avec l'attribut serialized_name, on force le nom à être 'fille'. Mais ce n'est vraiment pas une méthode propre avis.

L'un des objectifs d'une API REST est d'avoir une interface uniforme. Si à chaque réponse, le client doit adapter son code pour la traiter correctement, c'est un signe que tu t'éloignes des principes de base de REST.

Mon problème ne se pose pas tellement lorsque je charge un élément mais un ensemble d'éléments. Dans mon cas cet ensemble est affiché dans un tableau avec seulement quelques informations clé et le reste des informations est afficher dans la fenêtre si on sélectionne un élément dans ce tableau.

Du coup si l'utilisateur final n'en sélectionne que un et qu'on à charger 15 éléments… on aura charger 14 éléments détaillé pour rien.

Pour gagner en bande passante mais également en temps de traitement serveur (le problème de faire avec la méthode que tu propose est que l'on ne gagne malheureusement rien du tout coté serveur puisque l'entité entière est chargée pour récupérer son id… alors qu'en fait l'id est la clé étrangère donc directement dans l'entité de base)

J'étais en train de me dire que des API telle que celle de github devaient probablement faire de même du coup je suis allé voir… sauf que manifestement ce n'est pas le cas, du coup je suis en train de me dire que je dois juste me contenter d'éviter d'inclure trop de sous-éléments (donc qu'une entité appelle une sous entité qui appelle une sous entité, …)

Merci d'avoir regardé à mon problème :) t'es génial ^^

+0 -0

Si tu utilises Doctrine, la solution est donc d'utiliser des jointures dans tes repositories lorsque tu fais tes requêtes. Cela optimisera grandement ton code et en une requête, tu auras toutes les informations dont tu as besoin.

Il est aussi bon de rappeler que Doctrine utilise par défaut le lazy loading. En gros, même si tu as un objet Fille, tant que tu n'essayes pas de lire un attribut autre que la clé primaire, Doctrine ne fait pas de requêtes supplémentaires pour récupérer tous les attributs de ton objet (il existe quelques cas où cela n'est pas possible).

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