I am having annoying problems with persisting an entity with one or more OneToMany-Childs.
I have a "Buchung" entity which can have multiple "Einsatztage" (could be translated to an event with many days)
In the "Buchung entity I have
/**
* @param \Doctrine\Common\Collections\Collection $property
* @ORM\OneToMany(targetEntity="Einsatztag", mappedBy="buchung", cascade={"all"})
*/
private $einsatztage;
$einsatztage is set to an ArrayCollection() in the __constructor().
Then there is the "Einsatztag" Entity wich has a $Buchung_id variable to reference the "Buchung"
/**
* @ORM\ManyToOne(targetEntity="Buchung", inversedBy="einsatztage", cascade={"all"})
* @ORM\JoinColumn(name="buchung_id", referencedColumnName="id")
*/
private $Buchung_id;
Now If I try to persist an object to the database the foreign key of the "Einsatztag" Table is allways left empty
$buchung = new Buchung();
$buchung->setEvent( $r->request->get("event_basis"));
$buchung->setStartDate(new \DateTime($r->request->get("date_from")));
$buchung->setEndDate(new \DateTime($r->request->get("date_to")));
$von = $r->request->get("einsatz_von");
$bis = $r->request->get("einsatz_bis");
$i = 0;
foreach($von as $tag){
$einsatztag = new Einsatztag();
$einsatztag->setNum($i);
$einsatztag->setVon($von[$i]);
$einsatztag->setBis($bis[$i]);
$buchung->addEinsatztage($einsatztag);
$i++;
}
$em = $this->getDoctrine()->getManager();
$em->persist($buchung);
foreach($buchung->getEinsatztage() as $e){
$em->persist($e);
}
$em->flush();
Firstly, you have to understand that Doctrine and Symfony does not work with id's within your entities.In Einsatztag entity, your property should not be called $Buchung_id since it's an instance of buchung and not an id you will find out there.
Moreover, in your loop, you add the Einsatztag to Buchung. But do you process the reverse set ?
I do it this way to always reverse the set/add of entities.
Einsatztag
public function setBuchung(Buchung $pBuchung, $recurs = true){
$this->buchung = $pBuchung;
if($recurs){
$buchung->addEinsatztag($this, false);
}
}
Buchung
public function addEinsatztag(Einsatztag $pEinsatztag, $recurs = true){
$this->einsatztages[] = $pEinsatztag;
if($recurs){
$pEinsatztag->setBuchung($this, false);
}
}
Then, when you will call
$buchung->addEinsatztag($einsatztag);
Or
$einsatztag->set($buchung);
The relation will be set on both side making your FK to be set. Take care of this, you'll have some behavior like double entries if you do not use them properly.
SImplier , you can use default getter/setters and call them on both sides of your relation, using what you already have, like following:
$einsatztag->set($buchung);
$buchung->addEinsatztag($einsatztag);
Hope it helped ;)
First of all, don't use _id
properties in your code. Let it be $buchung
. If you want it in the database, do it in the annotation. And this also the reason, why it's not working. Your are mapping to buchung
, but your property is $Buchung_id
<?php
/** @ORM\Entity **/
class Buchung
{
// ...
/**
* @ORM\OneToMany(targetEntity="Einsatztag", mappedBy="buchung")
**/
private $einsatztage;
// ...
}
/** @ORM\Entity **/
class Einsatztag
{
// ...
/**
* @ORM\ManyToOne(targetEntity="Product", inversedBy="einsatztage")
* @JoinColumn(name="buchung_id", referencedColumnName="id")
**/
private $buchung;
// ...
}
You don't have to write the @JoinColumn
, because <propertyname>_id
would the default column name.
I'm going to ignore the naming issue and add a fix to the actual problem.
You need to have in the adder method a call to set the owner.
//Buchung entity
public function addEinsatztage($einsatztag)
{
$this->einsatztags->add($einsatztag);
$ein->setBuchung($this);
}
And to have this adder called when the form is submitted you need to add to the form collection field the by_reference
property set to false
.
Here is the documentation:
Similarly, if you're using the CollectionType field where your underlying collection data is an object (like with Doctrine's ArrayCollection), then by_reference must be set to false if you need the adder and remover (e.g. addAuthor() and removeAuthor()) to be called.
http://symfony.com/doc/current/reference/forms/types/collection.html#by-reference