Doctrine 2 l'Héritage de la Cartographie avec l'Association
REMARQUE : si ce que je veux n'est pas possible, un "pas possible" réponse sera acceptée
Dans le Doctrine 2 de la documentation sur mappage de l'héritage, il est dit il y a 2 façons :
- Unique de l'héritage de table (STI)
- Classe de l'héritage de table (CTI)
Pour les deux, il y a l'avertissement :
Si vous utilisez un STI/CTI entité plusieurs-à-un ou un-à-un entité vous ne devez jamais utiliser l'une des classes dans les niveaux supérieurs de l'héritage de la hiérarchie comme “targetEntity”, seuls ceux qui n'ont pas de sous-classes. Sinon Doctrine NE peut pas créer de proxy cas de cette entité et sera TOUJOURS à la charge de l'entité avec impatience.
Alors, comment puis-je procéder utiliser l'héritage, avec un lien vers la base (résumé) de la classe ? (et conserver les performances de cours)
Exemple
Un utilisateur a plusieurs Pet
(classe abstraite prolongée par Dog
ou Cat
).
Ce que je veux faire :
class User {
/**
* @var array(Pet) (array of Dog or Cat)
*/
private $pets;
}
En raison de l'avertissement dans la Doctrine de la documentation, je devrais le faire :
class User {
/**
* @var array(Dog)
*/
private $dogs;
/**
* @var array(Cat)
*/
private $cats;
}
C'est gênant, parce que je perds les avantages de l'héritage !
Remarque : je n'ai pas ajouter de la Doctrine des annotations pour la cartographie de base de données, mais vous pouvez comprendre ce que je veux dire
- bonne question, vous avez probablement cibler les chiens et les chats spereratly
- Oui, mais ce n'est pas ce que je veux faire :p
- même ici :-/ j'ai la même situation avec des nœuds (les pages / articles / choses) et de commentaires
- Rappelez-vous, il est juste un avertissement. Je l'ai ignoré cet avertissement cause il semble comme il n'y a pas de solution pour elle. J'ai accepté que, dans ces cas, il ne prendra pas en charge les serveurs proxy. Juste un choix entre la présentation technique et de la performance. Je choisis la première... Mais toujours curieux de savoir si il ya une solution pour cela quelque part.
- Quelque chose doit m'échapper, mais je serais ravi de vous aider. Vous pouvez peut-être élargir votre question à inclure des exemples de ce que vous voulez faire opposition à ce que vous vous sentez comme vous avez à faire? Comme la question qui est écrit maintenant, il me semble qu'il aurait besoin de quelqu'un pour être dans le même état d'esprit typique de la Doctrine de l'utilisateur, dont je ne suis pas 🙂
- J'ai prolongé l'exemple pour être plus clair, faites le moi savoir si c'est mieux. Merci
- pourquoi ne pouvez-vous pas simplement d'ajouter une méthode getPets qui fusionnera les chiens et les chats et de les renvoyer?
- Ce n'est pas une mauvaise idée, mais c'est un travail que l'héritage est censé s'occuper de :(. Et si je veux ajouter un animal de compagnie, je dois avoir quelques commutateur ou ifs avec
instanceof
... Beaucoup de choses bizarres pour une chose si simple. Je vais garder cela à l'esprit si aucune solution ne se lève.
Vous devez vous connecter pour publier un commentaire.
Je suis fatigué, mais cela semble être beaucoup de bruit pour rien.
Vous avez manqué les bits importants de cet avertissement:
Ce n'est pas le cas dans ton exemple! Si vous n'avez pas omis la doctrine des annotations, vous pourriez avoir remarqué.
L'association de l'Utilisateur::animaux de compagnie est OneToMany, ce n'est pas [Un|Plusieurs]ToOne. Un utilisateur a plusieurs animaux de compagnie.
L'association inverse est OneToOne, mais c'est le ciblage de l'Utilisateur, qui n'a pas d'héritage.
Robin réponse aurait été une bonne idée -- vous pouvez vous connecter les requêtes sql et de voir ce que la doctrine ne fait à votre base de données!
La mauvaise performance scénario est quelque chose comme:
Maintenant, si vous voulez parcourir toutes les cols bleus, la Doctrine heurte à quelques difficultés. Il ne sait pas quelle classe $propriétaire va être, donc il ne peut pas utiliser un Proxy. Au lieu de cela, il est forcé d'impatience charge $propriétaire pour savoir si c'est un Chat ou un Chien.
Ce n'est pas un problème pour OneToMany ou ManyToMany relations, parce que dans ce cas, le chargement paresseux fonctionne très bien. Au lieu d'une procuration, vous obtenez un PersistentCollection. Et un PersistentCollection est toujours un PersistentCollection. Il ne s'occupe pas de son propre contenu jusqu'à ce que vous demandez d'eux. Si paresseux chargement fonctionne très bien.
OneToMany
, vous devez utiliser leManyToOne
annotation sur le côté inverse. Vous "parler" à propos de l'inverse du côté de l'Entité, et non pas de la relation de l'Entité.Je pense que vous avez mal compris, la section de ce manuel, vous avez cité est intitulé "l'impact de la Performance", ils ne sont pas en vous disant que vous ne peut pas ce faire, seulement qu'il y a des implications sur les performances si vous le faites. Cela a un sens pour le chargement paresseux - pour des collections hétérogènes de la STI entités, vous devez aller à la base de données et la charge de l'entité avant que vous savez dans quelle classe il sera, donc, le chargement paresseux n'est pas possible /n'a pas de sens. Je suis en train d'apprendre la Doctrine de 2 moi en ce moment, donc j'ai fait la maquette de votre exemple, les travaux suivants OK pour plus d':
... et le script de test ....
Tous mes chats et les chiens charge que le type correct:
Si vous regardez le code SQL généré, vous remarquerez que lorsque le OneToMany targetEntity est "animal de compagnie", vous obtenez SQL comme ceci:
Mais quand il est réglé à Chat, vous obtenez ceci:
HTH.
inversedBy="id"
dans votre Animal de compagnie de classe suppose de travailler? Ce serait jeter une Doctrine d'erreur: "...se réfère à l'inverse du côté de champ Entity\User#id qui n'est pas définie comme l'association".