2016-06-09 10 views
1

Ich habe eine Situation, in der ich Spalten zu einer Viele-zu-Viele Join-Tabelle hinzufügen muss, also versuche ich die empfohlene Praxis der Join-Tabelle durch eine Entität mit ManyToOne-Beziehungen mit jedem der anderen beiden vertreten Entitäten.Doctrine ManyToMany Association Entity: Warum löscht removeXXX() den zugrunde liegenden Datenbankeintrag nicht?

In diesem Fall haben wir ein Gericht Dolmetscher-Management-System, wo es eine Entität namens Event, eine andere namens Interpreter. Die InterpreterAssignment-Entität ist Eins-zu-Viele mit beiden, benötigt aber auch zwei Metadatenspalten: eine created datetime und die Application\Entity\User, die sie erstellt hat (ich lasse letzteres der Einfachheit halber aus).

So funktioniert das ganz gut:

$interpreter = $entityManager->getRepository('Application\Entity\Interpreter') 
    ->findOneBy(['lastname'=>'Mintz']); 
$assignment = new Entity\InterpreterAssignment(); 
$assignment->setInterpreter($interpreter)->setEvent($event); 
$event->addInterpretersAssigned($assignment); 
$em->flush(); 

... und ich brauche nicht einmal persist() zu sagen, weil der cascade={"persist","remove"}) auf Event#interpretersAssigned.

aber wenn ich versuche, das Gegenteil zu tun, das heißt, die removeInterpretersAssigned() Methode verwenden, die Lehre für mich schrieb:

$event = $entityManager->find('Application\Entity\Event',103510); 
$assignment = $event->getInterpretersAssigned()[0]; 
$event->removeInterpretersAssigned($assignment); 
$em->flush(); 

die Datenbank unberührt; Doctrine löscht die Zeile in der Join-Tabelle nicht.

Ich kann umgehen mit sagen $entityManager->remove($assignment). Aber ich kann nicht anders, als zu denken, dass $event->removeInterpretersAssigned($assignment) soll funktionieren.

Also, ich muss etwas vermissen, aber ich kann nicht sehen was. Das Doctrine cli-Tool sagt, dass meine Mappings in Ordnung sind. Hier sind die Einheiten in relevanten Teilen:

/* namespace declarations and use statements omitted */ 

class Event 
{ 

    /* other fields and methods omitted */ 

    /** 
    * @ORM\OneToMany(targetEntity="InterpreterAssignment",mappedBy="event",cascade={"persist","remove"}) 
    * @var InterpreterAssignment[] 
    */ 
    protected $interpretersAssigned; 

    /* the following created by the Doctrine cli tool */ 

    /** 
    * Remove interpretersAssigned 
    * 
    * @param \Application\Entity\InterpreterAssignment $interpretersAssigned 
    */ 
    public function removeInterpretersAssigned(\Application\Entity\InterpreterAssignment $interpretersAssigned) 
    { 
     $this->interpretersAssigned->removeElement($interpretersAssigned); 
    } 

    /** 
    * Get interpretersAssigned 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getInterpretersAssigned() 
    { 
     return $this->interpretersAssigned; 
    } 
} 

class Interpreter 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="InterpreterAssignment",mappedBy="interpreter") 
    * @var InterpreterAssignment[] 
    */ 
    protected $assignments; 

    /** 
    * Remove assignment 
    * 
    * @param \Application\Entity\InterpreterAssignment $assignment 
    */ 
    public function removeAssignment(\Application\Entity\InterpreterAssignment $assignment) 
    { 
     $this->assignments->removeElement($assignment); 
    } 

    /** 
    * Get assignments 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getAssignments() 
    { 
     return $this->assignments; 
    } 
} 

und hier ist der InterpreterAssignment

/** 
* @ORM\Entity 
* @ORM\Table(name="interp_events", uniqueConstraints={@ORM\UniqueConstraint(name="unique_deft_event",columns={"interp_id","event_id"})}) 
* @ORM\HasLifeCycleCallbacks 
*/ 

class InterpreterAssignment 
{ 

    /** 
    * @ORM\Id 
    * @ORM\ManyToOne(targetEntity="Interpreter",inversedBy="assignments") 
    * @ORM\JoinColumn(name="interp_id", referencedColumnName="interp_id") 
    * @var Interpreter 
    */ 
    protected $interpreter; 

    /** 
    * @ORM\Id 
    * @ORM\ManyToOne(targetEntity="Event",inversedBy="interpretersAssigned") 
    * @ORM\JoinColumn(name="event_id", referencedColumnName="event_id") 
    * @var Event 
    */ 
    protected $event; 


    /** 
    * @ORM\Column(type="datetime",nullable=false) 
    * @var \DateTime 
    */ 
    protected $created; 

    /** 
    * @ORM\PrePersist 
    */ 
    public function onPrePersist() 
    { 
     $this->created = new \DateTime(); 
    } 

    /** 
    * Set interpreter 
    * 
    * @param \Application\Entity\Interpreter $interpreter 
    * 
    * @return InterpreterAssignment 
    */ 
    public function setInterpreter(\Application\Entity\Interpreter $interpreter) 
    { 
     $this->interpreter = $interpreter; 

     return $this; 
    } 

    /** 
    * Get interpreter 
    * 
    * @return \Application\Entity\Interpreter 
    */ 
    public function getInterpreter() 
    { 
     return $this->interpreter; 
    } 

    /** 
    * Set event 
    * 
    * @param \Application\Entity\Event $event 
    * 
    * @return InterpreterAssignment 
    */ 
    public function setEvent(\Application\Entity\Event $event) 
    { 
     $this->event = $event; 

     return $this; 
    } 

    /** 
    * Get event 
    * 
    * @return \Application\Entity\Event 
    */ 
    public function getEvent() 
    { 
     return $this->event; 
    } 

    /* other stuff ommitted */ 
} 

Vielen Dank.

Antwort

0

Ich glaube, Sie brauchen zwei Dinge zu tun:

  1. (optional) Sie müssen $assignment->setEvent(null) rufen nach $event->removeInterpretersAssigned($assignment);

  2. Auch rufen Sie möchten Orphan Removal verwenden, um die Einheit von den vielen zu entfernen zu vielen Tisch. und so sollte das Unternehmen Code geändert (man beachte die Zugabe von , orphanRemoval=true zum Mapping-Code):

    /** 
        * @ORM\OneToMany(targetEntity="InterpreterAssignment",mappedBy="event",cascade={"persist","remove"}, orphanRemoval=true) 
        * @var InterpreterAssignment[] 
        */ 
    protected $interpretersAssigned; 
    
+0

Dies funktioniert. Vielen Dank! Die einzige zusätzliche Modifikation, die notwendig war, war die Signatur der 'InterpreterAssignment' Entität zu ändern. SetEvent() akzeptiert NULL: 'public function setEvent (Ereignis $ event = null)' – David

+0

BTW: Ich sehe klarer, warum einige Leute gegen ORM protestieren . Wenn die Eigenschaft "$ event" von "InterpreterAssignment" NULL-zulässig ist, ist dies nicht zulässig. Bemerkenswert ist, dass ich die Spalte in der Datenbank nicht nullbar machen konnte. – David

Verwandte Themen