0

我正在使用 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 传输的数据模型,在我看来这是一个普遍的缺点,无法按照我提出的方式进行操作。

4

1 回答 1

1

我建议使用 DoctrineprePersist事件来处理这个问题。如果prePersist您需要编写一些逻辑来检查数据库以确定是否doorType存在。

如果存在,doorType则从数据库中获取并使用它而不是在反doorType序列化淘汰 JSON 时创建的对象。

如果它不存在,请保留doorType从您的未序列化剔除 JSON 创建的那个,然后保留您的Door.

http://docs.doctrine-project.org/en/latest/reference/events.html

于 2013-09-27T16:09:01.283 回答