我正在使用 Durandal/Knockoutjs 构建一个前端应用程序和一个带有 Symfony2 的 Web 服务后端,我使用 Doctrine 来访问数据库。
我有两个实体是一对多关联的,像这样
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name = "drew_cat_door")
*/
class Door
{
public function __construct()
{
//$this->setAddTime(new \DateTime(date('Y-m-d H:i:s')));
if ($this->getAddTime() == null)
$this->setAddTime(new \DateTime(date('Y-m-d H:i:s')));
else
$this->setUpdateTime(new \DateTime(date('Y-m-d H:i:s')));
}
/**
* @ORM\Id
* @ORM\Column(type = "integer")
* @ORM\GeneratedValue(strategy = "AUTO")
*/
protected $id;
/**
* @ORM\Column(type = "string", length = 30)
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity = "DoorType", inversedBy = "doors")
* @ORM\JoinColumn(name = "type_id", referencedColumnName = "id")
*/
protected $type;
/**
* @ORM\Column(type = "string", length = 30, nullable = true)
*/
protected $filename;
/**
* @ORM\Column(type = "string", length = 100, nullable = true)
*/
protected $description;
/**
* @ORM\Column(type = "integer", nullable = true)
*/
protected $views;
/**
* @ORM\Column(type = "datetime")
*/
protected $add_time;
/**
* @ORM\Column(type = "datetime", nullable = true)
*/
protected $update_time;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Door
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set filename
*
* @param string $filename
* @return Door
*/
public function setFilename($filename)
{
$this->filename = $filename;
return $this;
}
/**
* Get filename
*
* @return string
*/
public function getFilename()
{
return $this->filename;
}
/**
* Set description
*
* @param string $description
* @return Door
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set views
*
* @param integer $views
* @return Door
*/
public function setViews($views)
{
$this->views = $views;
return $this;
}
/**
* Get views
*
* @return integer
*/
public function getViews()
{
return $this->views;
}
/**
* Set add_time
*
* @param \DateTime $addTime
* @return Door
*/
public function setAddTime($addTime)
{
$this->add_time = $addTime;
return $this;
}
/**
* Get add_time
*
* @return \DateTime
*/
public function getAddTime()
{
return $this->add_time;
}
/**
* Set update_time
*
* @param \DateTime $updateTime
* @return Door
*/
public function setUpdateTime($updateTime)
{
$this->update_time = $updateTime;
return $this;
}
/**
* Get update_time
*
* @return \DateTime
*/
public function getUpdateTime()
{
return $this->update_time;
}
/**
* Set type
*
* @param \Drewkol\AdminBundle\Entity\DoorType $type
* @return Door
*/
public function setType(\Drewkol\AdminBundle\Entity\DoorType $type = null)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* @return \Drewkol\AdminBundle\Entity\DoorType
*/
public function getType()
{
return $this->type;
}
}
/**
* @ORM\Entity
* @ORM\Table(name = "drew_cat_doortype")
*/
class DoorType
{
public function __construct()
{
$this->doors = new ArrayCollection();
if ($this->getAddTime() == null)
$this->setAddTime(new \DateTime(date('Y-m-d H:i:s')));
else
$this->setUpdateTime(new \DateTime(date('Y-m-d H:i:s')));
}
/**
* @ORM\Id
* @ORM\Column(type = "integer")
* @ORM\GeneratedValue
*/
protected $id;
/**
* @ORM\Column(type = "string", length = 30)
*/
protected $name;
/**
* @ORM\OneToMany(targetEntity = "Door", mappedBy = "type")
*/
protected $doors;
/**
* @ORM\Column(type = "datetime")
*/
protected $add_time;
/**
* @ORM\Column(type = "datetime", nullable = true)
*/
protected $update_time;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return DoorType
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set add_time
*
* @param \DateTime $addTime
* @return DoorType
*/
public function setAddTime($addTime)
{
if ($addTime != null)
$this->add_time = $addTime;
return $this;
}
/**
* Get add_time
*
* @return \DateTime
*/
public function getAddTime()
{
return $this->add_time;
}
/**
* Set update_time
*
* @param \DateTime $updateTime
* @return DoorType
*/
public function setUpdateTime($updateTime)
{
$this->update_time = $updateTime;
return $this;
}
/**
* Get update_time
*
* @return \DateTime
*/
public function getUpdateTime()
{
return $this->update_time;
}
/**
* Add doors
*
* @param \Drewkol\AdminBundle\Entity\Door $doors
* @return DoorType
*/
public function addDoor(\Drewkol\AdminBundle\Entity\Door $doors)
{
$this->doors[] = $doors;
return $this;
}
/**
* Remove doors
*
* @param \Drewkol\AdminBundle\Entity\Door $doors
*/
public function removeDoor(\Drewkol\AdminBundle\Entity\Door $doors)
{
$this->doors->removeElement($doors);
}
/**
* Get doors
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getDoors()
{
return $this->doors;
}
}
抱歉没有省略任何代码。如您所见,一个 Door 有一个 DoorType。
因为这很容易,所以在添加门时,我发布了一个 JSON
{"name":"nowe","type":{"id":5,"name":"loluk","add_time":"2013-09-25T01:05:05+0200"},"description":"hehe\n","filename":"hehe.jpg"}
并且是一个已经存在的类型的全门实体模型。当我尝试使用此代码添加带有教义的实体时
$json_door = $this->get("request")->getContent();
if (empty($json_door))
return $this->createBadRequestException();
$door = $this->container->get("serializer")
->deserialize($json_door, "Drewkol\\AdminBundle\\Entity\\Door", "json");
$door->setAddTime(new \DateTime(date('Y-m-d H:i:s')));
$manager = $this->getDoctrine()->getManager();
$manager->persist($door);
$manager->flush();
我收到一条错误消息
A new entity was found through the relationship 'Drewkol\AdminBundle\Entity\Door#type' that was not configured to cascade persist operations for entity: Drewkol\AdminBundle\Entity\DoorType@000000002d1b74500000000063b1c8fb. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Drewkol\AdminBundle\Entity\DoorType#__toString()' to get a clue.
我的问题是:用已经添加的类型添加门的最干净和有效的方法是什么?
如果要添加的实体中给出的类型已经在数据库中(因为它必须在之前添加过) ,有什么方法可以告诉 Doctrine 尝试解决,还是我必须从 JSON 反序列化实体中获取并删除类型防止它被持久化(使用建议的级联选项),然后使用 Doctrine 获取类型,然后将其设置为我全新的反序列化门实体的类型,以便 Doctrine 知道类型?我的意思是我喜欢由 knockoutjs 生成并使用 JSON 传输的数据模型,在我看来这是一个普遍的缺点,无法按照我提出的方式进行操作。