Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Symfony 5] héritage d'entité User

bundle

    4 août 2021 à 18:16:13

    Bonjour,

    j'ai créé un bundle qui me permet grosso-modo de gérer les utilisateurs (inscription, connexion, rappel de mot de passe, etc).

    J'ai ensuite créé plusieurs bundles correspondant à mes fonctionnalités effectives (qui n'ont pas grand chose à voir les unes avec les autres d'où le besoin de séparer).

    Dans les bundles "applicatifs", j'ai aussi une gestion d'utilisateur mais plutôt selon la notion de propriétaires (relations oneToMany / ManyToMany).

    J'essaye donc de faire hériter mes entités User applicatives de l'entité User de mon bundle de gestion utilisateur mais j'ai des soucis de cohérence.

    J'ai testé 36 trucs mais aucun ne me convient (soit ça n'est pas logique, soit ça réclame de presque tout dupliquer / surcharger)...

    Fonctionnellement, ce qui se rapproche le plus de ce que je veux faire c'est le "single table inheritance" de Doctrine mais je ne veux pas que l'entité parente ait connaissance de ses potentielles entités enfants (pour rester le plus générique possible) donc ça ne fonctionne évidemment pas (puisque la discriminator map devrait être définie dans le parent).

    Ex :

    j'ai une classe UserBundle/Entity/User très basique (login, mdp, etc)

    et une classe TrucMucheBundle/Entity/User qui extends UserBundle/Entity/User et ajoute une propriété
    que n'a pas UserBundle/Entity/User (et que n'ont pas les entités User d'autres bundles).

    J'ai essayé :

    • single table inheritance mais comme indiqué, souci avec la discriminator map
    • mappedSuperClass : je ne sais plus ce que j'avais comme erreurs mais ça ne fonctionnait pas
    • classe UserBundle/Entity/User abstraite : souci avec la connexion / inscription
    • UserInterface et UserManager : ça fonctionne presque mais trop de code à surcharger et de configuration à dupliquer... (et Symfony n'est pas capable d'autowiring donc obligée de toute expliciter...)
    • j'ai fini par faire un truc tout dégueu (mais qui fonctionne ><) : indiquer dans le bundle UserBundle (censé être générique) l'entité enfant (en la nommant pareil dans tous les bundles applicatifs) mais ça ne me plaît pas ^^ : https://github.com/DelPlop/sf-user-bundle
    Comment m'en sortir en conservant le bundle UserBundle le + générique possible et en ayant le moins de code à surcharger / dupliquer dans les bundles qui vont l'utiliser ?
    Merci de vos idées lumineuses ^^

    -
    Edité par Luunia 5 août 2021 à 13:59:24

    • Partager sur Facebook
    • Partager sur Twitter
      4 août 2021 à 19:50:28

      Bonjour, 

      Une relation OneToMany ou ManyToOne (dépendant de qui est propriétaire de la relation) suffira pour ton use case. 

      Par contre, pourquoi est ce que tu mets en place des bundles sous symfony5 ???! Les bundles c'est déprécié et une ancienne pratique abandonné depuis la version 4. Je ne comprends pas du tous ta notion et mise en place de bundle pour le coup. Quel est utilité ? 

      Cordialement,

      • Partager sur Facebook
      • Partager sur Twitter
        4 août 2021 à 21:05:59

        à terme, je veux avoir toutes mes fonctionnalités dans une même app d'où le besoin de séparer tout (sachant que lesdites fonctionnalités n'ont rien à voir les unes avec les autres)

        la relation que tu indiques, elle devrait être entre quoi et quoi ?

        il y a déjà une relation entre l'entité propriétaire (disons ApplicationUser) et ses machins (Article dans mon exemple)

        si c'est une relation entre UserBundle/User et BiduleBundle/ApplicationUser alors c'est plus OneToOne (mais j'aimerais éviter d'en arriver là ^^)

        -
        Edité par Luunia 4 août 2021 à 21:06:28

        • Partager sur Facebook
        • Partager sur Twitter
          4 août 2021 à 22:16:13

          J'arrive vraiment pas à saisir le fait d'avoir des bundles. Sans utiliser ton système de "bundle" tu auras quand même toutes tes fonctionnalités dans ton app. En terme de fonctionnalité, quelles sont ces fonctionnalités qui n'ont "rien à avoir entre elles" ? 

          La relation serait entre ton entité UserBundle/User et BiduleBundle/ApplicationUser. Pourquoi veux tu éviter d'en arrivé là ? 

          (Et tu devrais vraiment revoir ton architecture, ou bien revoir la doc symfony et les best practices concernant les bundles c'est vraiment pas une bonne pratique, ayant souvent des clients qui font tourner leur application grâce à symfony, je n'ai pour ma part jamais vu de "bundle" depuis la version 4).

          • Partager sur Facebook
          • Partager sur Twitter
            5 août 2021 à 7:56:21

            Bonjour,

            Mon grain de sel ... 

            Effectivement la structure bundle dans une appli a été dépréciée depuis Symfony 4.

            La notion de bundle existe encore si on veut partager un module avec la communauté Symfony. Ce qui ne semble ni ton besoin ni ton envie.

            Symony 4 puis 5 permettent bien de séparer les fonctionnalités sans se baser sur la notion de bundle mais en jouant entre autres sur les namespaces.

            Je ne vois pas très bien où tu veux en venir mais le simple exemple plus haut que tu donnes avec l'entité Article m'incite à penser que tu mélanges les besoins.

            En quoi un article (si la notion se rapporte à un post, de la presse, ...un document écrit) ferait partie d'un User ?

            Un user peut écrire un article, modifier un article, etc mais la notion d'article n'est pas une propriété d'une personne.

            Et dans ce cas, la solution est simple c'est une relation entre User et l'entité Article (one2many ou many2many suivant ton fonctionnel). Il n'y a pas besoin d'héritage non plus.

            A+

            -
            Edité par monkey3d 5 août 2021 à 9:24:10

            • Partager sur Facebook
            • Partager sur Twitter
              5 août 2021 à 10:31:18

              tout d'abord, merci pour vos réponses

              ensuite, je réexplique avec des exemples concrets, ce sera plus clair (j'espère ^^)

              fonctionnellement

              je veux, d'un côté, gérer la notion d'utilisateur de l'application (inscription, connexion, reset mdp, gestion des rôles/ACL, etc)

              d'un autre côté, j'ai plusieurs applis : une app de vidéothèque, une app de liste de gestion de ma collection de bijoux, etc

              elles n'ont rien à voir entre elles (fonctionnellement) mais j'aimerais éviter de maintenir 5 ou 6 apps Symfony (la v6 arrivera tôt ou tard), donc je voudrais, à terme, qu'elles soient toutes sur le même socle technique (j'ai pas encore réfléchi à cette partie mais c'est pas le sujet de toute façon)

              techniquement

              la gestion de l'authentification est commune => bundle UserBundle (pour l'intégrer en vendor dans chaque app ; c'est l'équivalent très très simplifié du FosUserBundle pour ceux qui l'ont connu ^^)

              d'autre part, certaines de mes apps ont aussi une notion d'utilisateur (qui fonctionnellement est différente de l'authentification) qui "possède" des entités (ex : un utilisateur possède un ou plusieurs DVD/Blu-Ray, un utilisateur possède un ou plusieurs bijoux)

              d'où l'héritage : mon Application/User hérite des propriétés de UserBundle/User (login, mdp) et y ajoute les propriétés "métier" liées à l'application ($videos, $bijoux, etc)

              du coup, dans certains cas, j'ai besoin de vérifier, d'une part, que l'utilisateur est connecté et, d'autre part, qu'il est bien "propriétaire" de l'entité (par ex pour la modifier ou la supprimer)

              je voudrais éviter d'avoir une relation entre UserBundle/User et AppBundle/ApplicationUser pour éviter d'avoir 36 tables en base

              mais peut-être est-ce la meilleure manière de faire (j'avoue que je ne l'ai pas encore testée ^^)

              après, j'admets que les bundles ne sont peut-être pas une bonne solution (mais j'envisage de les partager, c'est d'ailleurs déjà le cas d'une de ces applis) donc, si je pars sur des namespaces, comment :

              • avoir la gestion commune de l'authent en vendor (pour éviter 50 copier-coller en cas de modif) ?
              • garder la possibilité de partager une ou plusieurs de ces applis (en vendor pour que les gens puissent les intégrer comme ils le souhaitent) ?
              merci !

              -
              Edité par Luunia 5 août 2021 à 10:33:25

              • Partager sur Facebook
              • Partager sur Twitter
                5 août 2021 à 11:11:22

                Quand tu parles d'applis, ce sont vraiment des applis web indépendantes ou seulement des modules d'une appli web unique ?

                Quand aux exemples indiqués, le fait qu'un utilisateur possède plusieurs BlueRay se traduit par une relation OnetoMany et il n'y a pas besoin de chercher plus loin.

                Le User n'est pas propriétaire d'une entité mais des objets d'une entité éventuellement.

                Si c'est une seule appli web unique alors il y a une gestion des User (voir la doc Symfony) qui ne nécessitent pas de faire un bundle.

                Si c'est plusieurs applis web qui repose sur la même gestion de user alors effectivement faire un bundle type FosUserBundle peut avoir du sens pour l'intégrer ensuite dans les différentes applis.

                Une autre solution c'est de faire une appli centrale de gestion des Users et de définir une API Rest qui donc permet aux autres applis de se servir de l'API.

                A+

                -
                Edité par monkey3d 5 août 2021 à 12:15:29

                • Partager sur Facebook
                • Partager sur Twitter
                  5 août 2021 à 11:57:49

                  actuellement, c'est des applis complètement séparées mais j'envisage d'en regrouper certaines (quand j'aurais réussi à faire fonctionner l'existant correctement)

                  dans tous les cas, une des apps est destinée à être partagée (donc doit pouvoir rester totalement indépendante des autres)

                  le User (au sens "qui est connecté ?") n'est effectivement "propriétaire" de rien, c'est le "membre" ou "utilisateur de l'application" qui possède des choses mais mon problème n'est pas là (ça fonctionne très bien ça)

                  mon problème se situe au niveau de comment articuler les 2 notions "utilisateur" et comment faire fonctionner mon bazar ^^

                  je manipule soit des objets de type BundleUser/User (et donc les propriétés "métier" n'existent pas) soit de type ApplicationUser (et donc les fonctionnalités liées à l'authentification déconnent car ça attend le type parent BundleUser/User)

                  je veux éviter d'avoir à redéfinir toute la conf dans l'app "enfant" pour pouvoir utiliser le UserBundle

                  je testerai ce soir la relation One2One entre BundleUser/User et ApplicationUser

                  -
                  Edité par Luunia 5 août 2021 à 14:02:44

                  • Partager sur Facebook
                  • Partager sur Twitter
                    5 août 2021 à 12:09:44

                    Je ne comprends pas :

                    donc les fonctionnalités liées à l'authentification déconnent car ça attend le type parent

                    Mais quel type parent si c'est une relation entre des objets métiers et l'objet User ???? Une relation, ce n'est pas un héritage.

                    Je ne vais pas poursuivre la discussion car je pense avoir donné des solutions si j'ai bien compris la problématique, ce dont je ne suis pas sûr.

                    Même si le FosUserBundle n'est plus d'actualité, tu peux toujours t'inspirer en regardant le code et la doc pour la notion d'intégration et de surcharge mais à mon avis ce n'est pas vraiment la solution à ton besoin.

                    Bye

                    -
                    Edité par monkey3d 5 août 2021 à 12:17:34

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 août 2021 à 13:54:40

                      depuis le début je parle uniquement de User : BundleUser/User (=parent) et ApplicationBundle/User (=enfant)

                      et j'ai bien fait hériter ApplicationBundle/User de BundleUser/User (comme déjà dit 2x)

                      j'ai expliqué le reste autour pour expliquer pourquoi j'ai séparé

                      c'est l'autre posteur qui m'a suggéré de remplacer mon héritage par une relation ce que je n'ai pas (encore) fait (mais que je testerai, on verra bien ce que ça donne)

                      j'ai essayé une manière dérivée du FosUserBundle, mais ça fait trop de code à surcharger ou dupliquer dans l'app "fille" donc ça ne me convient pas non plus

                      -
                      Edité par Luunia 5 août 2021 à 14:03:36

                      • Partager sur Facebook
                      • Partager sur Twitter
                        5 août 2021 à 15:24:04

                        Je t'ai suggérer aussi la relation car pour ma part c'est ce que je fais :

                        - j'ai une gestion des users classique et relativement simple et tout un tas de relations (bi-directionnelles ou pas) sur des domaines comme l'audiothèque, vidéothèque, ... chat texte, recette de cuisine, domotique, etc avec User. Je n'utilise pas l'héritage juste des relations.

                        Je n'arrive toujours pas à comprendre de qu'est ton ApplicationBundle/User. Il me semble que tu es partie sur une idée d'héritage qui n'est pas la solution à ton problème.

                        On utiliserait l'héritage pour décrire un User basique et des Users dérivés par héritage qui peuvent par exemple dans une école : le tronc commun user et des dérivés, professeur, élève, administratif, etc. Chacun possède le tronc commun mais les différents types de User ont des propriétés complémentaires.

                        Pour gérer les Blu-Ray des users il suffit comme je crois l'avoir dit plus haut de faire une relation (OneToMany) entre l'entité qui gère les Blu-Ray (disons Video) et l'entité User.

                        Bye

                        • Partager sur Facebook
                        • Partager sur Twitter
                          5 août 2021 à 15:29:36

                          Hello,

                          "L'autre posteur" mais on est où là ! Tu peux citer mon pseudo directement hahaha trève de plaisanterie je comprends mieux ton besoin.

                          Partons sur une base de "2 applications" à savoir la vidéothèque et un gestionnaire de collection de bijoux qui tournent sur un seul et même projet Symfony. 

                          Il faudrait que tu crées 2 dossiers "VideoLibrary" et "JewelleryBook" dans chaques sous-dossiers du dossier "src"

                          Tu aurais donc: 

                          • src/Controller/VideoLibrary
                          • src/Controller/JewelleryBook
                          • src/Entity/VideoLibrary
                          • src/Entity/JewelleryBook
                          • src/Repository/VideoLibrary
                          • src/Repository/JewelleryBook

                          Ainsi, tous les controllers associés à la vidéothèque seront centralisés dans un même dossier. Pareil pour la gestion des bijoux et ainsi de suite.

                          Même si tu dis que fonctionnellement elle n'ont rien à avoir, tu devrais plutôt les voir comme des "modules" de ton site et n'ont pas 2 applications distinctes étant donnés qu'elles tournent sur le même projet. (Tu pourrais avoir cette distinction de 2 applications mais il faudrait que tu créer un Kernel pour chaque application, c'est d'un niveau avancé..).

                          Concernant l'authentification, du point de vue architecture logicielle, c'est une excellente pratique de vouloir isoler l'entité User afin qu'elle ne gère seulement que l'authentification. 

                          Par contre, lorsque tu parles de BundleUser/User et ApplicationUser/User, tu mélanges un peu. Tu devrais avoir une seul entité User au sain de ton application, elle fais officie de carte d'identité. 

                          A coté pour ta vidéothèque au lieu d'avoir Entity/VideoLibrary/User, tu aurais une entité beaucoup plus "parlante". Exemple Entity/VideoLibrary/Subscriber qui sera un abonné de ta vidéothèque et qui possédera plusieurs dvd/bluray, autre exemple Entity/JewelleryBook/Collector qui sera un collectionneur qui possédera un ou plusieurs bijoux.

                          Ainsi c'est beaucoup plus parlant dans ton code d'avoir une notion de Subscriber pour la vidéothèque et Collector pour les bijoux. Ces 2 entités sur lié à ton entités user en OneToOne. Et par ce biais, tu auras accès à toutes les infos User (email, mot de passe etc). 

                          Dans un language courant, lorsqu'un collectionneur sera connecté à ton site, pour connaitre son identité tu lui demanderas sa carte d'identité (comme un controle de police). Dans le code, ca se traduira par cela: 

                          $collector->getUser(); // Retourne l'objet User
                          $collector->getUser()->getRoles(); // Retourne les roles de l'utilisateur au sein de l'application
                          $subscriber->getUser();
                          $subscriber->getUser()->getEmail();


                          Voilà, j'espère que ce sera clair, tu n'as nullement besoin de faire de l'héritage et encore moins d'avoir des bundles.

                          -
                          Edité par Murthog7331 5 août 2021 à 15:30:21

                          • Partager sur Facebook
                          • Partager sur Twitter
                            5 août 2021 à 15:36:24

                            @Murthog7331 : je crois que nous disons la même chose sur les principes mais tu as bien détaillé les grosses mailles de la solution.

                            Ouf !

                            Cette fois je change de sujet.

                            Bye

                            • Partager sur Facebook
                            • Partager sur Twitter
                              5 août 2021 à 17:28:06

                              oui donc en revient toujours à la même chose : une relation OneToOne

                              je testerai donc, comme prévu :D

                              merci !

                              • Partager sur Facebook
                              • Partager sur Twitter
                                8 août 2021 à 16:52:08

                                salut @Murthog7331 j'ai testé plusieurs solutions et décidé de tout changer ^^

                                mais j'aimerais quand même que l'entité User qui sert pour l'authent (appelons-la RegisteredUser) n'ait aucune connaissance de ce qui l'utilise (et c'est là ça bloque car la relation OneToOne doit être définie dans les 2 sens ><)

                                avec l'inheritance doctrine, j'aurais le même souci, le "parent" doit connaître ses enfants...

                                comment faire un truc générique, indépendant, réutilisable et éventuellement partageable ?

                                Merci,

                                • Partager sur Facebook
                                • Partager sur Twitter

                                [Symfony 5] héritage d'entité User

                                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                • Editeur
                                • Markdown