2012-10-09 20 views
13

Non riesco a trovare un modo per estendere in modo appropriato un'entità tra i bundle in Symfony2 utilizzando Doctrine2 come ORM.Estensione di entità in Symfony2 con Doctrine2

Attualmente ci sono tre metodi che ho trovato per estendere entità in Symfony2 usando Doctrine2 come ORM. Mapped Superclass, Single Table Inheritance e Class Table Inheritance. Nessuno di questi lavori funziona per quello che sto cercando di fare.

Ho due pacchetti: UserBundle e BlogBundle. Voglio essere in grado di utilizzare UserBundle in progetti che non hanno il BlogBundle, ma il BlogBundle sarà sempre utilizzato nei progetti che hanno il pacchetto utente. Va bene se BlogBundle ha dipendenze da UserBundle, ma non viceversa.

ho due entità: BlogBundle \ Entity \ postali e UserBundle \ Entity \ User

Relazione: Ci deve essere un uno a molti tra gli utenti e post sul blog. Questo risultato è ottenuto attraverso una proprietà author_id (colonna) sull'oggetto BlogBundle \ Entity \ Post (tabella) che viene mappato a UserBundle \ Entity \ User.id

Il problema: posso chiamare l'UserBundle \ Entity \ Entità utente direttamente dall'interno di BlogBundle e ottenere ciò che sto cercando utilizzando una mappatura unidirezionale. Questo non mi consente di accedere a tutti i messaggi di un utente da un oggetto Utente. Posso accedere ai dati tramite query personalizzate, ma non è così semplice come accedere ai post da un utente tramite l'oggetto utente.

Quello che mi piacerebbe fare è estendere l'oggetto Utente UserBundle \ Entity \ dall'interno del BlogBundle, e aggiungere i metodi e le proprietà di questo oggetto che stabiliscono l'Uno a Molti mappatura utilizzato all'interno del BlogBundle. Niente di tutto ciò è persistente, semplicemente definisce la relazione e mi consente di accedere logicamente a tutti i post creati da un utente in un'applicazione che implementa sia il BlogBundle che il UserBundle aggiungendo funzionalità necessarie all'oggetto User all'interno del bundle del blog (evitando così una dipendenza da UserBundle a BlogBundle).

Quando creo un oggetto BlogBundle \ Entity \ User ed estendo UserBundle \ Entity \ User, devo dichiarare @ORM \ Table (name = "usertablename"). In caso contrario, qualsiasi tentativo di accesso all'oggetto BlogBundle \ Entity \ User non accederà al database. Poiché nessuna delle aggiunte nell'oggetto esteso persiste, questo funziona bene tra i pacchetti. Il problema è quando chiamo "php app/console doctrine: schema: update --force", c'è un conflitto poiché due entità cercano di mappare a & creare la stessa tabella. Ho provato a utilizzare la funzione ResolveTargetEntityListener che è stata implementata di recente ma che, insieme a Mapped Superclas, STI e CTI forzano tutti una dipendenza da BlogBundle dal UserBundle.

Di seguito sono riportati i miei oggetti per illustrare la mia configurazione. Sono stati abbreviati per chiarezza. Mi rendo conto che alcune delle semantiche non sono corrette, ma ha lo scopo di comunicare la configurazione delle idee &.

UserBundle \ Entity \ User

@ORM\Table(name="app_user") 
@ORM\Entity 
class User implements UserInterface 
{ 
    ... 
} 

BlogBundle \ Entity \ Messaggio

@ORM\Table(name="app_post") 
@ORM\Entity 
class Post 
{ 
    ... 

    @ORM\Column(name="author_id", type="integer") 
    protected $author_id; 

    @ORM\ManyToOne(targetEntity="\App\BlogBundle\Entity\User", inversedBy="posts") 
    @ORM\JoinColumn(name="author_id", referencedColumnName="id") 
    protected $author; 
} 

BlogBundle \ Entity \ User

use App\UserBundle\Entity\User as BaseUser 
@ORM\Entity 
@ORM\table(name="app_user") 
class User extends BaseUser 
{ 
    .... 

    @ORM\OneToMany(targetEntity="App\BlogBundle\Entity\Post", mappedBy="author") 
    protected $posts; 

    public function __construct() 
    { 
     parent::_construct(); 

     $this->posts = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    .... 
    /* Getters & Setters, nothing that defines @ORM\Column, nothing persisted */ 
} 

Questo funziona, ma il problema è che sono mappare due entità nel progetto alla stessa tabella. L'oggetto esteso non cattura @ORM \ Table (name = "app_user") dal suo parent, quindi deve essere definito in BlogBundle \ Entity \ User. Se nessun riferimento a questo oggetto da un controller non accederà al database. Dal momento che nulla è persistito dall'oggetto esteso nulla è rotto tranne quando cerco di aggiornare lo schema del database dalla console.

Posso usare una relazione unidirezionale, ma questo limita il modo in cui posso accedere ai dati da un controller.

+0

So che questa è una domanda molto vecchio ; ma l'hai mai risolto? Sto affrontando gli stessi problemi e sto lottando per trovare soluzioni operative. – bigstylee

risposta

6

Si può vedere a questo link per conoscere l'eredità: http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance

È necessario dichiarare in UserBundle \ Entity \ User:

/** 
* @Entity 
* @InheritanceType("SINGLE_TABLE") 
* @DiscriminatorColumn(name="discr", type="string") 
* @DiscriminatorMap({"baseuser" = "UserBundle\Entity\User", "blogUser" = "BlogBundle\Entity\User"}) 
*/ 
class User implements UserInterface 
{ 
    ... 
} 

E BlogBundle \ Entity \ User

use App\UserBundle\Entity\User as BaseUser; 
/** 
* @ORM\Entity 
*/ 
class User extends BaseUser 
{ 
    .... 
} 

In bocca al lupo!

+1

Non penso che questa sia una soluzione soddisfacente, dal momento che esiste un riferimento da parte di UserBundle a BlogBundle in '@ DiscriminatorMap'. Sarei interessato a una soluzione in cui UserBundle non abbia alcun riferimento/dipendenza da BlogBundle. – aimfeld

0

Penso che si potrebbe trovare questo Bundle interessante:

https://github.com/mmoreram/SimpleDoctrineMapping

Esso consente di definire da parametri quali file vengono Mapping la vostra entità, permettendo di ignorare ogni entità dei tuoi pacchi generici.

Ad esempio:

parameters: 

    # 
    # Mapping information 
    # 
    test_bundle.entity.user.class: "TestBundle\Entity\User" 
    test_bundle.entity.user.mapping_file_path: "@TestBundle/Mapping/Class.orm.yml" 
    test_bundle.entity.user.entity_manager: default 
    test_bundle.entity.user.enable: true 

L'unica controindicazione che vedo è che è necessario definire tutte le entità prossimi allo stesso modo perché si è disabilitata auto_mapping ...

Problemi correlati