我有两个实体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();
答案 0 :(得分:0)
您的代码中有两个问题:
第一个:你将每个Slaholiday
持续两次:首先是
$this->_em->persist($holiday);
,第二个
foreach ($slaplan->getHolidays() as $value) {
$this->_em->persist($value);
}
实际上没有问题,因为在调用flush
之前它们实际上并没有保留在数据库中,但无论如何,您不需要foreach
。
您的联接表未更新的原因是$slaplan->setHolidays
方法。您正在使用$slaplan->holidays
初始化ArrayCollection
(这是正确的),并在setHolidays
中将其设置为输入参数($allholidays
Array
,这是不对。)
因此,正确的方法是使用ArrayCollection
的{{3}}方法
public function setHolidays($holidays)
{
//$this->holidays->clear(); //clears the collection, uncomment if you need it
foreach ($holidays as $holiday){
$this->holidays->add($holiday);
}
}
OR
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);
答案 1 :(得分:0)
虽然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
中执行相同操作。
现在当你向Slaplan添加一个Slaholiday时,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添加到它,保留Slaplan中的cascade
并从Slaholiday中删除它。