2013-06-05 4 views
5

Ich stehe vor einem Problem, das auch auf programmers.stackexchange.com liegen könnte, aber da es ziemlich eng mit Doctrine und ZF2 verbunden ist, habe ich es aufgesetzt hier. Lassen Sie mich Ihnen mein Szenario vorstellen:Wie man mit verschiedenen Entity-Eigenschaften für verschiedene Entity-Kategorien umgeht

  • Ich habe eine Anwendung, wo Benutzer Entitäten (BaseEntity) senden.
  • Die BaseEntity hat die Eigenschaft $cagetory
  • auf $category Je jedoch die Entity zusätzliche Eigenschaften

Ab einfaches Beispiel haben muss:

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

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

Jetzt konnte ich leicht ein zweistufigen formular tun wo ein Benutzer zuerst seine Kategorie auswählt und abhängig davon wird die EntityClass ausgewählt - aber ich kann das nicht haben. Aber das ist nicht gut, denn was ist, wenn der User einen Film in der BaseEntity-Kategorie anlegt und später dann die Entity in MovieEntity ändern will? Diese Idee ist also keine sichere Option.

Zusätzliche Anforderungen (um Sachen komplizierter)

  • den Kategorien sowie Entities haben durch Lehre
  • Jeder Category vorgesehen ist über eine einzige Module
  • der Anwendung gesteuert werden Module müssen in die Anwendung platziert werden, ohne dass viel Konfiguration benötigt wird (bei maximal einer DB-Abfrage, um die CategoryTable zu befüllen)

Was ich

Zuerst bisher habe ich gewählt mit Doctrines Funktionalität Single Table Inheritance laufen. Dies erlaubte mir, Dinge wie MovieEntity extends BaseEntity leicht zu machen und die Dinge funktionieren wie ein Zauber, um neue Entitäten zur Datenbank hinzuzufügen. Aber das Hauptproblem bleibt: Was passiert, wenn der Benutzer die Kategorie ändert, würde das die EntityClass ändern und das ist so ziemlich ein No-Go.

Ich meine ja, ich könnte potentiell Dinge meine aktuelle Art und Weise und auf den Wechsel der Kategorie manuell ändern die DiscriminatorColumn, aber das ist so verdammt schmutzig.

Ein anderer alternativer Ansatz wäre, dass bei der Änderung der Kategorie eine NEUE Entität erstellt wird und die alte zerstört wird, aber das fühlt sich auch irgendwie schmutzig an.

Alles in allem denke ich, dass ich in die falsche Richtung gehe. Es mag ein Entwicklungsmuster geben, von dem ich nicht weiß, dass all meine harte Arbeit wie eine Verschwendung aussieht und die Dinge am Ende sehr einfach werden, aber es scheint, dass ich Dinge übersehe.

vielleicht um eine genauere Vorstellung von dem, was ich bin, du einen Blick auf meiner Anwendung auf GitHub hast:

Vielen Dank im Voraus für all das Feedback erhalte ich kann. Ich bin völlig klar, dass diese Frage wahrscheinlich eine Grenze zwischen einer Existenz von SO vs Programmierer ist. Stackexchange, aber ich entschied mich dafür, es hier doch zu haben.

Antwort

3

Wenn ich Ihre Situation richtig lese, klingt es so, als wäre Ihnen die Vermeidung von Vererbung bei Thing besser und stattdessen kategoriespezifische Attribute als Eigenschaften der Beziehung zwischen Things und Categories.

Was ist eine Architektur wie folgt aus:

<?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; 
} 

So, jetzt Dinge zwischen den Kategorien durch Ersetzen des ThingCategory Einheit mit ihr verbundenen bewegen kann. Die Identität der Sache ändert sich nie, nur ihre Beziehung zur Kategorie. Die Attribute, die für die Aufnahme in diese Kategorie erforderlich sind, sind Eigenschaften der ThingCategory-Relationsentität, nicht der Thing selbst.

BEARBEITEN: Das Problem, auf das Sie stoßen können, ist, dass es keine dokumentierte Möglichkeit gibt, die Diskriminator-Map zu modifizieren, wenn Entitäten abgeleitet werden. Der unglückliche Nebeneffekt ist, dass Ihr Basismodul über jedes mögliche Modul Bescheid wissen muss. Aber das ist wahrscheinlich keine große Sorge. Wenn dies der Fall ist, glaube ich, dass es möglich ist, dies zu vermeiden, indem jedes Modul die ClassMetaData für die Basis-Entity manipuliert, aber ich habe mich nie darum gekümmert, diese Arbeit zu machen.

+0

Hey Tim, danke für deine Eingabe, dass das Design klarer aussieht als das was ich bisher in meiner Anwendung gemacht habe, also danke für die Eingabe. Das Problem, das ich sehe (obwohl ich falsch liegen kann), ist immer noch der CHANGE einer Kategorie. Würde Ihr Beispiel die 'discriminatorColumn' innerhalb der 'Entity' automatisch aktualisieren, wenn eine andere Kategorie ausgewählt ist? Ich werde das sicherlich testen! PS: Um die DiscriminatorMapping von bestimmten Modulen zu erweitern: siehe [my onBootstrap() eines SubModuls] (https://github.com/manuakasam/DuitMarketplaceItemVehicle/blob/master/Module.php#L35-L48) – Sam

+1

Sam, ich don denke ich, es gibt nur ein 'Ding' (oder' BaseEntity'). Das, was "BaseEntity" von "MovieEntity" unterscheidet, wurde in die verschiedenen Kategorien verschoben. Was ich jedoch in der Lösung von timdev vermisse, ist, wie die Werte jener Eigenschaften gespeichert werden, die durch die Kategorie nach 'Thing' definiert sind. Es gibt eine Entity 'ThingCategoryProperty', die eine ManyToOne-Assoziation mit' Thing' und 'Category' hat. Übrigens, Sam, ich mag die Art, wie du den dynamischen Inhalt des 'DiskriminatorMappings' gelöst hast! – netiul

+0

@Sam - Nein, wenn Sie die Kategorie wechseln, löschen Sie eine ThingSomeCategory und fügen eine andere ThingSomeCategory ein. – timdev

1

Ihr Problem ist dieser Satz "Aber das Hauptproblem bleibt: was ist, wenn der Benutzer die Kategorie ändert, würde es die EntityClass ändern und das ist so ziemlich ein No-Go."

Eine Kategorie würde sich nicht wirklich ändern, sie würde entfernt und durch eine neue ersetzt werden. Übermitteln Sie dies in Ihrem Code, erstellen Sie eine neue Entität, behalten Sie sie bei, aktualisieren Sie alle Referenzen, um auf die neue Entität zu zeigen, und löschen Sie dann die alte Entität.

+0

Ich werde mit diesem Design-Prinzip für jetzt gehen, einfach weil es die wenigsten Änderungen an meiner aktuellen Anwendung bedeutet. Obwohl ich den Code zu einem späteren Zeitpunkt, wenn ich mehr Zeit habe, umbauen muss – Sam