2013-06-05 26 views
5

Sono di fronte a un problema, che può essere inserito anche su programmers.stackexchange.com, ma poiché è abbastanza legato a Doctrine e ZF2, ho scelto di inserirlo qui. Permettetemi di presentarvi il mio scenario:Come gestire diverse proprietà di entità per diverse categorie di entità

  • Ho un'applicazione in cui gli utenti inviano entità (BaseEntity).
  • Il BaseEntity ha la proprietà $cagetory
  • A seconda $category l'entità ha però avere proprietà aggiuntive

Ab semplice Esempio:

class BaseEntity { 
    protected $id; 
    protected $title; 
    protected $description; 
} 

class MovieEntity { 
    protected $id; 
    protected $title; 
    protected $description; 
    protected $airingDateStart; // new property 
    protected $airingDateEnd; // new property 
} 

Ora ho potuto facilmente fare un formulario in due fasi dove un utente sceglie per prima cosa la sua Categoria e in base alla quale verrà scelto EntityClass - ma non posso averlo. Ma non va bene, perché se l'Utente crea un film nella BaseEntity -Categoria e successivamente desidera modificare l'Entità in MovieEntity? Quindi quell'idea non è davvero un'opzione sicura.

Requisiti aggiuntivi (per fare cose più complicate)

  • Le categorie così come entità devono essere controllati da Dottrina
  • Ogni Category viene fornito per l'applicazione tramite un unico Module
  • I moduli devono essere inseriti nell'applicazione senza molta configurazione necessaria (al massimo una DB-Query per popolare il CategoryTable)

quello che ho fatto finora

In un primo momento ho scelto di correre con funzionalità Dottrine Single Table Inheritance. Questo mi ha permesso di fare facilmente cose come MovieEntity extends BaseEntity e le cose funzionano come un fascino per l'aggiunta di nuove Entità al Database. Ma il problema principale rimane: cosa succede se l'utente cambia la categoria, cambierebbe EntityClass e questo è praticamente un No-Go.

Voglio dire sì, potenzialmente potrei fare le cose nel mio modo attuale e sul cambio di categoria modificare manualmente il DiscriminatorColumn ma è così spaventosamente sporco.

Un altro approccio alternativo sarebbe quello in caso di modifica della categoria, verrà creata una NUOVA Entità e la vecchia verrà distrutta, ma anche questa sembra sporca.

Tutto sommato penso di essere diretto nella direzione sbagliata. Potrebbe esserci un modello di sviluppo che non conosco, il che rende tutto il mio duro lavoro un rifiuto e alla fine le cose si rivelano super-facili, ma sembra che trascuri le cose.

Per ottenere forse un idea più vicino di quello che sto per, si può avere uno sguardo a mia domanda su GitHub:

Grazie in anticipo per tutti i feedback io possa avere. Comprendo perfettamente che questa domanda è probabilmente al limite tra un'esistenza su SO vs programmers.stackexchange, ma ho scelto di averlo qui, dopo tutto.

risposta

3

Se sto leggendo la tua situazione giusta, sembra che tu possa essere meglio servito evitando l'ereditarietà di Thing, e invece di attributi specifici di categoria come proprietà della relazione tra Cose e Categorie.

Che dire di un'architettura in questo modo:

<?php 

class Category { 
    protected $id; 
    protected $title; 
    protected $things; //@ManyToOne(targetEntity="ThingCategory") 
} 

class Thing { 
    protected $id; 
    protected $title; 
    protected $description; 
    protected $category; //@ManyToOne(targetEntity="ThingCategory") 
}  

/** 
* Use [Single|Class]-Table Inheritence to model subject-category attributes. 
* 
* ThingCategory is just a base class. Modules provide concrete subclasses 
* that encapsulate category-specific attributes. 
*/ 
class ThingCategory { 
    protected $id; //surrogate key, not strictly necessary 
    protected $thing; //@ManyToOne(targetEntity="Thing") 
    protected $category //@ManyToOne(targetEntity="Category") 
} 

class ThingMovieCategory extends ThingCategory{ 
    protected $airingStartDate; 
    protected $airingEndDate; 
} 

class ThingCarCategory extends ThingCategory { 
    protected $horespower; 
    protected $numberOfDoors; 
    protected $color; 
} 

Così, ora le cose possono muoversi tra le categorie sostituendo l'entità ThingCategory ad esso associati. L'identità della Cosa non cambia mai, è solo una relazione con la categoria. Gli attributi necessari per l'inclusione in quella categoria sono proprietà dell'entità relazione ThingCategory, non della Thing stessa.

MODIFICA: il problema che potresti incontrare è che non esiste un modo documentato di modificare la mappa discriminatrice quando si sottoclasse le entità. Lo sfortunato effetto collaterale è che il tuo modulo base dovrà sapere su ogni modulo possibile. Ma probabilmente non è una grande preoccupazione. Se lo è, credo che sia possibile evitare questo facendo in modo che ogni modulo manipoli ClassMetaData per l'entità di base, ma non mi sono mai preoccupato di farlo funzionare.

+0

Hey tim, grazie per il tuo contributo, quel design sembra più chiaro di quello che ho fatto nella mia applicazione fino ad ora, quindi grazie per l'input. Il problema che vedo (anche se potrei sbagliarmi) è ancora il CAMBIAMENTO di una categoria. Il tuo esempio aggiornerebbe automaticamente 'discriminatorColumn' all'interno di 'Entity' quando viene selezionata una categoria diversa? Lo metterò sicuramente alla prova! PS: Per estendere il DiscriminatorMapping da alcuni moduli: vedi [my onBootstrap() di un SubModule] (https://github.com/manuakasam/DuitMarketplaceItemVehicle/blob/master/Module.php#L35-L48) – Sam

+1

Sam, I don Credo di sì, c'è solo una cosa (o BaseEntity). Ciò che differenzia 'BaseEntity' da' MovieEntity' è stato spostato nelle diverse categorie. Quello che mi manca però nella soluzione di timdev, è come memorizzare i valori di quelle proprietà definite dalla categoria per "Cosa". C'è bisogno di un'entità 'ThingCategoryProperty' che abbia un'associazione ManyToOne con' Thing' e 'Category'. A proposito Sam, mi piace il modo in cui hai risolto il contenuto dinamico di 'DiscriminatorMapping'! – netiul

+0

@Sam - No, quando si cambia categoria, si elimina una ThingSomeCategory e si inserisce qualche altra ThingSomeCategory. – timdev

1

Il tuo problema è questa frase "Ma il problema principale rimane: cosa succede se l'utente cambia la categoria, cambierebbe EntityClass e questo è praticamente un No-Go."

Una categoria non cambierebbe davvero, verrebbe rimossa e sostituita con una nuova. Quindi rifletti su questo nel tuo codice, crea una nuova entità, persistila, aggiorna tutti i riferimenti per puntare alla nuova entità, quindi elimina la vecchia entità.

+0

Per ora andrò con questo principio del design, semplicemente perché significa le modifiche minime alla mia attuale applicazione. Anche se dovrò sicuramente rifattorizzare il codice in un secondo momento quando avrò più tempo – Sam

Problemi correlati