1

ich in Lehre Einheit die HaupteinheitWas ist der beste Weg/update Assoziation Nachschlagefelds

/** 
* @ORM\Entity() 
*/ 
class Document 
{ 
    /** 
    * @var int 
    * @ORM\Id() 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 
    /** 
    * @var DocumentStatus 
    * @ORM\ManyToOne(targetEntity="DocumentStatus") 
    */ 
    private $status; 
    /** 
    * @var string 
    * @ORM\Column(type="text") 
    */ 
    private $text; 
} 

und die Nachschlag „Enum“ Entität (auf Anfrage deploy Seeding)

/** 
* @ORM\Entity(repositoryClass="DocumentStatusRepository"); 
*/ 

class DocumentStatus 
{ 
    const DRAFT = 'draft'; 
    const PENDING = 'pending'; 
    const APPROVED = 'approved'; 
    const DECLINED = 'declined'; 
    /** 
    * @var int Surrogate primary key 
    * @ORM\Id() 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string Natural primary key (name for developers) 
    * @ORM\Column(type="string", unique=true) 
    */ 
    private $key; 
    /** 
    * @var string Short name for users 
    * @ORM\Column(type="string", unique=true) 
    */ 
    private $name; 
    /** 
    * @var string Full decription for users 
    * @ORM\Column(type="string", nullable=true, unique=true) 
    */ 
    private $description; 
} 

müssen eingestellt mit einfacher Repository

class DocumentStatusRepository extends EntityRepository 
{ 
    public function findOneByKey($key) 
    { 
     return parent::findOneBy(['key' => $key]); 
    } 
} 

ich mag Domain Logik des Dokumenten-Lebenszyklus verkapseln von Methoden intoducing wie

public function __construct($text) 
{ 
    $this->text = $text; 
    $this->status = $something->getByKey(DocumentStatus::DRAFT); 
} 

public function approve() 
{ 
    try { 
     $this->doSomeDomainActions(); 
     $this->status = $something->getByKey(DocumentSatus::DRAFT); 
    } catch (SomeDomainException($e)) { 
     throw new DocumentApproveException($e); 
    } 
} 
... 

oder

public function __construct($text) 
{ 
    $this->text = $text; 
    $this->status = $something->getDraftDocumentStatus() 
} 

public function approve() 
{ 
    $this->status = $something->getApprovedDocumentStatus() 
} 
... 

ohne öffentlichen Setter. Außerdem möchte ich das Dokument locker koppeln und testbar machen.

Ich sehe die nächsten Möglichkeiten:

  • Permanent inject DocumentStatusRepository (oder eine Dienstleistung, die es kapselt) in jedem Fall durch Konstruktor auf Unternehmen Schaffung und mit öffentlichen Setter in Postload Teilnehmer
  • Permanent inject DocumentStatusRepository durch statische Verwendung Document Methode auf Anwendung Bootstrap oder auf loadClassMetadata
  • Temporary injizieren DocumentStatusRepository in Konstruktor und Methoden wie Document :: Appreve
  • Verwenden Sie die Methode setStatus() mit c omplex Logik basierend auf $ status-> Schlüsselwert
  • Encapsulate Dokument Domain-Logik in einigen Documentmanager und Verwendung Document Unternehmen wie einfache Daten storgae oder DTO :(

Gibt es andere Möglichkeiten? Welcher Weg ist einfacher und bequemer auf lange Sicht?

Antwort

1
  1. Verwenden von generierten Identitäten für Dokument.
    Jetzt generieren Sie die Identität auf der Seite der Datenbank. So Sie save Dokument aus der Domänenperspektive in inkonsistentem Zustand. Entität/Aggregat should be identified, wenn es keine ID hat, sollte es nicht existieren.
    Wenn Sie wirklich an Datenbankserien interessiert sind, fügen Sie dem Repository eine Methode hinzu, die eine ID für Sie generiert.
    Besserer Weg ist UUID Generator zum Beispiel Ramsey/Uuid zu verwenden. Und inject die ID to the constructor.

  2. DocumentStatus als Wertobjekt
    Warum Dokumentstatus Entität? Es sieht wie ein einfaches Wertobjekt aus. Dann können Sie Embeddable Annotation verwenden. Es wird also innerhalb der gleichen Tabelle in der Datenbank belassen, keine inneren Joins erforderlich.
    DocumentStatus bekommt Verhalten zum Beispiel -> DraftDocumentStatus(), die returns NEW DocumentStatus mit Entwurfsstatus, so dass Sie die alte Instanz eins mit neuen wechseln können. ORM erledigt den Rest.

  3. DocumentStatusRepository
    Wenn Sie wirklich DocumentStatus als Einheit behalten wollen, was meiner Meinung nach is wrong Sie nicht DocumentStatusRepository haben sollte.
    Dokument ist Ihre aggregierte Wurzel und die only entrance an den DocumentStatus, sollte durch aggregierte Wurzel sein.
    So haben Sie nur DocumentRepository, die für rebuilding das gesamte Aggregat verantwortlich ist und saving es. Auch Sie sollten das Mapping ändern.
    Es sollte den Typ FETCH=EAGER haben, damit DocumentStatus zusammen mit dem Dokument abgerufen wird.
    Zweitens sollten Sie mit CASCADE=ALL und ORPHANREMOVAL=TRUE Mapping tun.
    Andernfalls, wenn Sie remove Document, DocumentStatus will stay in the database.

+0

1. Danke für den Rat. Ich verstehe den Nachteil von 'vor dem Einfügen' generierten Bezeichnern wie MySQL AUTOINCREMENT Feldern. – VolCh

+0

2. Ja, in den Geschäftsbegriffen ist es Value Object, aber wenn wir es als Embeddable verwenden, dann haben wir die Felder 'name' und 'description' in jedem Datensatz der Dokumententabelle. Es braucht viel Speicherplatz und macht die Datenbank denormalisiert. Auf der anderen Seite dienen 'name' und 'description' nur für UI-Aufgaben und im Grunde brauchen wir sie nicht in der Datenbank. Aber in der Funktion werden wir andere Felder wie "apllies_from_date" hinzufügen und die Datenbank-Constraint für document.status_id basierend auf dem Dokumenterstellungsdatum und dem Status ab dem Datum festlegen. Wir wollen also 'document_status' trotzdem in der Datenbank haben. – VolCh

+0

3. Dokument haben viele-zu-eins-Verbindung mit DocumentStatus. Bei der ersten Anwendungsbereitstellung haben wir keine Dokumente und haben vier document_status. Später werden wir Millionen Dokumente und die gleichen vier Status haben. Wenn wir ein Dokument entfernen, bleibt der Status in der Datenbank erhalten. Das Dokument ist nicht Eigentümer des DocumentStatus, wenn die letzte Entität (nicht ValueObject) ist. – VolCh

Verwandte Themen