2010-05-05 7 views
2

Je commence à travailler avec Symfony, j'ai trouvé de la documentation sur l'héritage. Mais aussi trouvé this discouraging article, ce qui me fait douter si Doctrine gère l'héritage du tout ...symfony + doctrine + héritage, comment les faire fonctionner?

Quelqu'un trouve-t-il une solution intelligente pour l'héritage dans Symfony + Doctrine?

À titre d'exemple, j'ai déjà structuré la base de données quelque chose comme ceci:

CREATE TABLE `poster` (
    `poster_id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_name` varchar(50) NOT NULL, 
    PRIMARY KEY (`poster_id`), 
    UNIQUE KEY `id` (`poster_id`), 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; 

CREATE TABLE `user` (
    `user_id` int(11) NOT NULL, 
    `real_name` varchar(50) DEFAULT NULL, 
    PRIMARY KEY (`user_id`), 
    UNIQUE KEY `user_id` (`user_id`), 
    CONSTRAINT `user_fk` FOREIGN KEY (`user_id`) REFERENCES `poster` (`poster_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

De là, la doctrine a généré cette "schema.yml":

Poster: 
    connection: doctrine 
    tableName: poster 
    columns: 
    poster_id: 
     type: integer(4) 
     fixed: false 
     unsigned: false 
     primary: true 
     autoincrement: true 
    user_name: 
     type: string(50) 
     fixed: false 
     unsigned: false 
     primary: false 
     notnull: true 
     autoincrement: false 
    relations: 
    Post: 
     local: poster_id 
     foreign: poster_id 
     type: many 
    User: 
     local: poster_id 
     foreign: user_id 
     type: many 
    Version: 
     local: poster_id 
     foreign: poster_id 
     type: many 
User: 
    connection: doctrine 
    tableName: user 
    columns: 
    user_id: 
     type: integer(4) 
     fixed: false 
     unsigned: false 
     primary: true 
     autoincrement: false 
    real_name: 
     type: string(50) 
     fixed: false 
     unsigned: false 
     primary: false 
     notnull: false 
     autoincrement: false 
    relations: 
    Poster: 
     local: user_id 
     foreign: poster_id 
     type: one 

Création d'un utilisateur pour cette structure avec les formulaires générés automatiquement par Doctrine ne fonctionne pas.

Toute idée sera appréciée.

+0

Je suis confus quant à la façon dont vous souhaitez appliquer l'héritage en fonction des données ci-dessus (votre SQL d'origine ne correspond pas au fichier .yml produit). Pouvez-vous élaborer sur ce que vous essayez de faire? – richsage

+0

Merci d'avoir répondu. Eh bien, il devrait corréler, car il a été généré avec Doctrine. Je l'ai fait recadrer pour me concentrer sur le problème. Je trouve juste bizarre les relations de table d'affiche, parce que ce sont des FK externes d'autres tables à la table d'affiche ... J'essaye juste de prolonger l'affiche avec l'utilisateur, c'est pourquoi j'ai fait user_id un FK de poser_id.S'il vous plaît dites-moi si je dois être plus précis. – ismaelmachado

+0

Mmm je vois maintenant (le truc 'Version' me confondait). Cela pourrait être plus facile si vous commencez par écrire le schéma en .yml en premier - je ne vois pas pourquoi Doctrine générerait ces autres relations à moins que vous ne génériez automatiquement à partir d'une base de données qui a déjà des FK en place. – richsage

Répondre

2

Après plusieurs mois de travail sur un projet utilisant à la fois l'agrégation de colonnes et l'héritage concret, je ne peux que dire une chose: rester loin de l'héritage concret! Vraiment. Supposons que vous ayez 3 tables: Média et Vidéo/Audio qui hérite de Média. Vous vous attendez à être en mesure de faire quelque chose comme:

Doctrine_Query::create() 
    ->from('Media m') 
    ->execute(); 

Eh bien, cela ne fonctionnera pas avec l'héritage concret. C'est juste sans valeur et n'a presque aucune utilisation pratique, sauf pour les méthodes d'héritage de modèle.

D'autre part, avec l'agrégation de colonnes, la table des médias aura une colonne « type » automagiquement ajouté, et vous permettra de choses telles que:

Doctrine_Query::create() 
    ->from('Video v') 
    ->execute(); 

qui renvoie une collection d'objets vidéo. Mais vous pouvez également le faire:

Doctrine_Query::create() 
    ->from('Media m') 
    ->execute(); 

Et vous obtiendrez un résultat mixte d'objets vidéo et audio. En tout cas, vous devriez vérifier le doctrine documentation. Mais faites attention car l'héritage et la doctrine peuvent rapidement devenir gênants.

+0

Merci pour le conseil, mais j'avais vraiment besoin d'une solution pour commencer à développer un projet et j'ai réussi à le faire fonctionner d'une manière ou d'une autre. Le problème est que l'agrégation de colonnes gère des objets ou des objets sur un seul supertable et je pense que c'est une mauvaise conception de base de données. Je suis vraiment déçu de la façon dont Doctrine gère mal l'héritage au niveau de la base de données. J'ai vu l'héritage concret comme une façon incomplète d'aller, donc j'ai généré le modèle basé dessus et ensuite modifié l'implémentation des tables. Cela fonctionne pour l'instant, voyons comment ça se passe. – ismaelmachado

0

Une solution pour séparer les données « vidéo » de dire des données « audio », mais toujours utiliser la même table pour stocker « médias » est la suivante:

Media: 
    columns: 
    name: { type: string(255), notnull: true } 
    description: { type: text } 

Video: 
    inheritance: 
    type: column_aggregation 
    keyField: type 
    keyValue: video 

Audio: 
    inheritance: 
    type: column_aggregation 
    keyField: type 
    keyValue: audio 

VideoData: 
    columns: 
    resolution_x: { type: integer, notnull: true } 
    resolution_y: { type: integer, notnull: true } 
    relations: 
    Video: { foreignAlias: Data, onDelete: CASCADE } 

AudioData: 
    columns: 
    sample_rate: { type: integer, notnull: true } 
    relations: 
    Audio: { foreignAlias: Data, onDelete: CASCADE } 

Quelque chose comme ça ... De cette façon, vous pouvez stockez tous vos 'médias' dans une table et récupérez-le comme mentionné ci-dessus par DuoSRX et toujours pas de données non pertinentes dans cette table. Bien sûr, vous devez le rejoindre, mais avec des clés étrangères indexées, cela ne devrait pas être du tout un hit de performance.

Questions connexes