2017-07-11 2 views
0

ein Unternehmen A gegeben, die mit Einheiten B und C durch die optional ManyToOne Beziehungen verbunden ist - was der beste Weg, um sicherzustellen, dass sein würde, dass nur eine dieser Beziehungen auf einem verwendet wird, Zeit (XOR)?Lehre XOR zwei Beziehungen auf einer Entität

Was ich versuche das folgende Bild veranschaulicht recht gut zu erreichen ist (Mächtigkeit dort anders angezeigt):

enter image description here

Natürlich kann ich sicherstellen, dass Referenzen unter einem Repository gültig sind Code oder anderswo, aber vielleicht gibt es eine "richtige" Möglichkeit, dies zu tun, indem Sie Doctrine Mapping-Funktionen verwenden?

A

/** 
* @ORM\Table(name="A") 
* @ORM\Entity(repositoryClass="Test\AppBundle\Repository\ARepository") 
*/ 
class A 
{ 
    /** 
    * @var 
    * @ORM\ManyToOne(targetEntity="B", inversedBy="as", cascade={"all"}) 
    */ 
    private $b = null; 

    /** 
    * @var null 
    * @ORM\ManyToOne(targetEntity="C", inversedBy="as", cascade={"all"})) 
    */ 
    private $c = null; 
} 

B

/** 
* @ORM\Table(name="B") 
* @ORM\Entity(repositoryClass="Test\AppBundle\Repository\BRepository") 
*/ 
class B 
{ 
    /** 
    * @var 
    * @ORM\OneToMany(targetEntity="A", mappedBy="b", cascade={"all"}) 
    */ 
    private $as = null; 
} 

C

/** 
* @ORM\Table(name="C") 
* @ORM\Entity(repositoryClass="Test\AppBundle\Repository\CRepository") 
*/ 
class C 
{ 
    /** 
    * @var 
    * @ORM\OneToMany(targetEntity="A", mappedBy="c", cascade={"all"}) 
    */ 
    private $as = null; 
} 

Antwort

1

Ich bin mir nicht bewusst ein Build-in-Lösung für diese (und es gibt keine beste Praxis für Lehre entweder), aber hier sind einige Gedanken, die Ihnen helfen könnten:

1. Mit Getter/Setter-Methoden auf "null" die $ b Assoziation, wenn $ c gesetzt wird und umgekehrt

würde wie folgt aussehen:

public function setB($b) { 
    $this->b = $b; 
    if($b !== null) { 
     $this->c = null; 
    } 
} 

Vorteil ist, dass es nicht Es ist möglich, dass Ihre Entität einen ungültigen Status hat, in dem sowohl $ b als auch $ c gesetzt sind. Die Lehre verwendet jedoch eine Reflexion, z. wenn Entitätsinstanzen aus persistenten Objekten erstellt werden, um den Aufruf __construct zu verhindern. Es könnte sein, dass es auch einen Grund für Setter-Methoden gibt, so dass Ihre Entität in einen unerwünschten Zustand gerät, aber ich kann meine Behauptung nicht substanziieren (vielleicht um irgendeine Art von schmutzigen Zustand zu verhindern).

Sie könnten dies auch als einen Nebeneffekt betrachten, der für Benutzer Ihrer Klasse A unerwünscht ist (besonders in einer einfachen Setter-Methode würden Sie dieses Verhalten nicht erwarten). Das müssen Sie in Ihrem Kontext erläutern.

Diese Lösung ist in Ordnung mit symfony Formen. Solange die Eigenschaften nicht öffentlich sind, die Formen System will call the setter methods:

Es sei denn, eine Eigenschaft, öffentlich ist, muss es einen „Getter“ haben und „Setter“ Verfahren, so dass die Formularkomponente kann Daten auf die erhalten und setzen Eigentum.

2. Mit Lifecycle Rückrufe

ich für diese Methode gehen persönlich würde wie ich denke, es ist einfacher zu verstehen ist.(Siehe documentation)

Beispiel PrePersist mit:

/** 
* @ORM\PrePersist 
* @ORM\PreUpdate 
*/ 
public function checkAssociations() 
{ 
    if($this->a !== null && $this->b !== null) { 
     // throw some error 
    } 
} 

Dieser Code ist

  • besser lesbar (imo), weil es ist mehr "Klartext-like" („Wenn a und b sind gesetzt, werfen einen Fehler ") als die Setter-Lösung
  • Weniger fehleranfällig (keine Garantie, dass Ihre Setter-Methoden aufgerufen werden)

Hoffe, dass hilft.

Wenn jemand mehr Informationen über die Setter-Aufrufe in Symfony hat, wäre das großartig.

+0

Danke, ich denke, ich werde mit den Lebenszyklus-Callbacks gehen, da der Setter-basierte Ansatz viel fehleranfälliger ist (wie die eine Sache, dann die andere - und frage mich, warum es mit der falschen Eins endet) –

Verwandte Themen