Таблица соединений не обновляется в ассоциации ManyToMany в доктрине 2 - PullRequest
1 голос
/ 09 сентября 2011

У меня есть буксирные объекты Slaplans и Slaholidays и таблица соединений slaplans_slaholidays. После создания двух Slaholidays объектов я сохраняю их оба, добавляю их к Slaplans и очищаю. Проблема заключается в том, что обновляются только таблицы slaplans и slaholidays, а таблицы соединений нет.

Slaplans Сущность:

<?php
namespace ZC\Entity;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Slaplans
 *
 * @Table(name="slaplans")
 * @Entity(repositoryClass="Repositories\Slaplans")
 */
class Slaplans
{         
   /*
    * @ManyToMany(targetEntity="Slaholidays",inversedBy="plans", cascade={"ALL"})
    * @JoinTable(name="slaplans_slaholidays",
    * joinColumns={@JoinColumn(name="slaplanid" ,referencedColumnName="slaplanid")},
    * inverseJoinColumns={@JoinColumn(name="slaholidayid" ,referencedColumnName="slaholidayid")})
    * }
     */
    private $holidays;

    public function __construct()
    {

        $this->holidays = new \Doctrine\Common\Collections\ArrayCollection();
    }

public function getHolidays() {
    return $this->holidays;
}
public function setHolidays($holidays)
{
    $this->holidays=$holidays;

}
/*public function addHoliday($holiday) {

    $this->holidays[]=$holiday;
}*/
}

Slaholidays Сущность:

<?php
namespace ZC\Entity;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Slaholidays
 *
 * @Table(name="slaholidays")
 * @Entity(repositoryClass="Repositories\Slaholidays")
 */
class Slaholidays
{
    /**
     * @var integer $slaholidayid
     *
     * @Column(name="slaholidayid", type="integer", nullable=false)
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $slaholidayid;

    /*
     *  @ManyToMany(targetEntity="Slaplans",mappedBy="holidays", cascade={"ALL"})
     */
    private $plans;

    /*public function getPlans(){
        return $this->plans;
    }*/
}

Код для сохранения сущностей:

$allholidays=array();
$holiday=$this->_em->getRepository('ZC\Entity\Slaholidays')->find($value);
$holiday=new ZC\Entity\Slaholidays();
//..sets holiday fields here
$this->_em->persist($holiday);
$allholidays[]=$holiday;

$slaplan->setHolidays($allholidays);
foreach ($slaplan->getHolidays() as $value) {
    $this->_em->persist($value);
}
$this->_em->persist($slaplan);
$this->_em->flush();

Ответы [ 2 ]

0 голосов
/ 01 сентября 2013

Хотя Doctrine проверяет сторону ассоциации на наличие вещей, которые необходимо сохранить, всегда важно синхронизировать обе стороны ассоциации.

Мой совет - иметь, добавлять и удалять (не задано) методы с обеих сторон, которые выглядят так:

class Slaplans
{
    public function getHolidays()
    {
        return $this->holidays->toArray();
    }

    public function addHoliday(Slaholiday $holiday)
    {
        if (!$this->holidays->contains($holiday)) {
            $this->holidays->add($holiday);
            $holiday->addPlan($this);
        }
        return $this;
    }

    public function removeHoliday(Slaholiday $holiday)
    {
        if ($this->holidays->contains($holiday)) {
            $this->holidays->removeElement($holiday);
            $holiday->removePlan($this);
        }
        return $this;
    }
}

Сделайте то же самое в Slaplan.

Теперь, когда вы добавляете Slaholiday в Slaplan, этот Slaplan также будетбыть добавленным в Slaholiday автоматически.То же самое касается удаления.

Так что теперь вы можете сделать что-то вроде этого:

$plan = $em->find('Slaplan', 1);

$holiday = new Slaholiday();
// set data on $holiday
// no need to persist $holiday, because you have a cascade={"ALL"} all on the association

$plan->addHoliday($holiday);
// no need to persist $plan, because it's managed by the entitymanager (unless you don't use change tracking policy "DEFERRED_IMPLICIT" (which is used by default))
$em->flush();

PS: не используйте cascade с обеих сторон ассоциации.Это сделает вещи медленнее, чем необходимо, а в некоторых случаях может привести к ошибкам.Если вы сначала создадите Slaplan, а затем добавите к нему Slaholidays, сохраните cascade в Slaplan и удалите его из Slaholiday.

0 голосов
/ 09 сентября 2011

В вашем коде есть две проблемы:

Первая: вы продолжаете каждый Slaholiday дважды: сначала с

$this->_em->persist($holiday);

, а затем с

foreach ($slaplan->getHolidays() as $value) {
    $this->_em->persist($value);
}

На самом деле проблем нет, поскольку они на самом деле не сохраняются в БД до вызова flush, но в любом случае вам это не нужно foreach.

Причина, по которой ваша таблица соединенийне обновляется в $slaplan->setHolidays методе.Вы инициализируете $slaplan->holidays с помощью ArrayCollection (что правильно), а в setHolidays вы устанавливаете его для входного параметра (который является $allholidays Array, а это неправильно).

Таким образом, правильный способ сделать это - использовать add метод ArrayCollection

public function setHolidays($holidays)
{
    //$this->holidays->clear(); //clears the collection, uncomment if you need it
    foreach ($holidays as $holiday){
        $this->holidays->add($holiday);
    }
}

ИЛИ

public function addHolidays(ZC\Entity\Slaholiday $holiday)
{
    $this->holidays->add($holiday);
}

public function clearHolidays(){
    $this->holidays->clear();
}
//..and in the working script...//

//..the rest of the script
$this->_em->persist($holiday);
//$slaplan->clearHolidays(); //uncomment if you need your collection cleaned
$slaplan->addHOliday($holiday);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...