Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1
Bonjour à tous,
depuis quelques jours, je m'essaie à l'intégration de Doctrine 2.
J'ai déjà une base de données existante et j'ai donc créé un mapping en fonction d'une table de cette bdd. Après la génération des entités liées (table avec plusieurs jointures), je suis confronté à un petit problème.
Voici le topo :
j'ai deux tables : Service et Translation.
Dans la table Service, j'ai certains champs qui sont remplis avec l'ID de la table Translation.
Voici la structure des deux tables :
[lang=php] Service : idservice (PRIMARY, AI) name (int) --------> stock un id de la table translation description (int) --------> stock un id de la table translation Translation : idtranslation (PRIMARY, AI) language (string) text (string)
Ce que je souhaite faire, c'est pouvoir récupérer le "translation.text" grâce à mon entity Service, pour chacun des champs "name" et "description".
Le problème, c'est, à mon avis, une relation de type OneToOne mais la table service ne présente pas de "foreign key" classique du type "translation_id". J'ai eu beau chercher dans la doc de Doctrine et sur internet, je n'ai pas trouvé de solutions...
A votre avis, comment pourrais-je résoudre ce problème ?
Merci d'avance pour vos réponses.
Romain
Dernière modification par RomainG (20-10-2015 13:18:22)
Hors ligne
Bonjour,
La j'ai pas tout compris de ton problème. As-tu du code qui ne fonctionne pas ou en est tu a l'étape d'étude de faisabilité (Sans avoir implémenté un truc mais juste y avoir réfléchi) ?
De ce que je comprends, tu souhaite récupérer du texte dans translation a partir de Service via le name ou la description ? Uniquement l'un des deux est renseigné ? Les deux sont renseigné ? Je ne vois pas trop l’intérêt d'avoir deux colonnes différente dans une même table faisant possiblement référence a la meme colonne de translation mais soit. Je n'ai pas toutes les informations.
Personnellement de ce que je comprend j'aurais créée une requêtes personnalisé dans le Repository de Service.
Du genre
[lang=sql] Select t.text from Service s Inner join Translation t ON t.idtranslation = s.name (ou s.description...) where s.name = :tonidTranslation
Après je suis peut être a coté de la plaque par rapport a ce que tu veux mais si j'ai bien compris ce que tu veux j'aurais utilisé les custom repository pour une requête moins standard.
Hors ligne
Salut,
alors pour l'instant, j'ai un peu de code que voici :
[lang=php] Class Service namespace Service\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; use Application\Entity\Translation; /** * @ORM\Table(name="service") * @ORM\Entity */ class Service { /** * @ORM\Column(name="idservice", type="integer", precision=0, scale=0, nullable=false, unique=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $idservice; /** * @ORM\Column(name="name", type="integer", precision=0, scale=0, nullable=false, unique=false) */ private $name; /** * @ORM\Column(name="type", type="integer", precision=0, scale=0, nullable=false, unique=false) */ private $type; /** * @ORM\Column(name="reference", type="string", length=10, nullable=true) */ private $reference; /** * @ORM\Column(name="description", type="integer", precision=0, scale=0, nullable=true, unique=false) */ private $description; /** * @ORM\Column(name="long_description", type="integer", precision=0, scale=0, nullable=true, unique=false) */ private $long_description; /** * @var \Service\Entity\Category * * @ORM\ManyToMany(targetEntity="Service\Entity\Category") * @ORM\JoinTable(name="category_service", * joinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="idservice")}, * inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="idcategory")}) */ private $categories; ????? private $serviceName; // getters & setters // .....
Pour l'instant, je n'ai que ça (j'essaie de comprendre au fur et à mesure !).
Pour clarifier les chose comme tu le demandes, le champs "name" ne peux être vide mais le champs "description" oui. Ces deux colonnes ne font évidement pas référence à la même colonne de la table Translation. On peux stocker l'ID 1 par exemple de la table translation pour le champs "name" et l'ID 2 pour le champs description.
Après, au niveau de mon ServiceRepository, j'ai ceci :
[lang=php] $qb = $this->em->createQueryBuilder(); $qb->select(['service']) ->from('Service\Entity\Service', 'service') ->leftjoin('Service\Entity\CategoryService', 'cs', 'WITH', 'service.idservice = cs.service_id') ->leftJoin('Service\Entity\Category', 'c', 'WITH', 'c.idcategory = cs.service_id') ->leftJoin('Application\Entity\Translation', 'tl3', 'WITH', 'c.name = tl3.idtranslation') ->leftJoin('Application\Entity\Translation', 'tl', 'WITH', 'service.name = tl.idtranslation') ->leftJoin('Application\Entity\Translation', 'tl2', 'WITH', 'service.description = tl2.idtranslation') ->groupBy('service.idservice'); $query = $qb->getQuery();
Hors ligne
Ok, j'ai saisi ou tu veux en venir,
De ce que je vois de ta requête, c'est quelle est incomplète.
Tu ne lui dit de te sélectionner que Service. Tu as les bon left join donc tu aura les traduction correspondantes, mais il faut que tu les sélectionnes.
Hors ligne
Oui, je comprends bien. J'avais testé en sélectionnant les traductions correspondantes et je les récupérais bien.
Le problème, c'est que j'avais un ensemble d'array du style :
[lang=php] array => 0 => object(Service\Entity\Service), 1 => object(Application\Entity\Translation) 2 => object(Service\Entity\Service) ...
Ce que j'aimerais bien avoir, c'est quelque chose du style :
[lang=php] array => 0 => object(Service\Entity\Service)[554] private 'idservice' => int 2 private 'name' => int 266 private 'type' => int 1 private 'reference' => null private 'description' => int 267 private 'long_description' => null private 'serviceName' => 'Mon object Translation' ...
Hors ligne
Je ne vois que l'utilisation d'une sous requete dans ton select au niveau de service name et description pour réussir a faire ce que tu veux.
Hors ligne
OK, je vois...
Je pensais que doctrine gérait ce cas de figure plus simplement en fait...
En tout cas, merci pour ton aide !
Hors ligne
C'est toujours possible mais j'ai des doutes. Si quelqu'un en as connaissance il se manifestera peut être.
Hors ligne
Salut, normalement doctrine peut le faire pour toi tout seul. Il suffit d'ajouter l'annotation qui va bien.
On va reprendre depuis le début. Tu as 2 tables, ces 2 tables ont des jointures entre elles mais ne respectent juste pas les conventions de nommage à savoir que dans ta table service tu as name à la place de translation_id et description à la place de translation_id. On est d'accord que de toute façon tu n'aurais pas pu avoir 2 fois translation_id dans la table.
Donc qu'est ce que tu aurais fait en temps normal. Tu aurais fait une relation OneToOne de Service vers Translation pour la colonne name et pour la colonne description. Pour que ça fonctionne via les noms de colonne tu aurais eu un truc du genre name_translation_id et description_translation_id (nom que tu peux choisir toi même). Donc à partir de là on se rapproche de ton cas de figure puisqu'il suffit de changer name_translation_id par name et description_translation_id.
Donc maintenant je te laisse trouver les bonnes annotations dans la doc de doctrine . C'est assez facile à trouver !
De cette façon lorsque tu feras un $service->getName() ou $service->getDescription() tu auras un objet Translation qui te sera retourné. Donc s'il y a une traduction associée tu pourras faire un $service->getName()->getText().
Dans le cas où la relation n'est pas OneToOne mais OneToMany tu auras une collection.
Hors ligne
Merci pour cette précision Orkin.
Au final, j'ai trouvé la solution hier en regardant une fois de plus la doc de doctrine !
Hors ligne
Pages: 1