Symfony Doctrine One to Many does not insert forei

2019-08-10 03:05发布

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();

3条回答
2楼-- · 2019-08-10 03:32

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 ;)

查看更多
再贱就再见
3楼-- · 2019-08-10 03:41

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

查看更多
The star\"
4楼-- · 2019-08-10 03:51

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.

查看更多
登录 后发表回答