Symfony 组合键和窗体
我的数据库中有以下关联(简化版): 这是一个多对多关联,但在联接表上有一个属性,所以 我有一个表单,我可以在其中添加任意多个关系到一个订单项,并同时创建它(主要受文档中教程的启发) 当我发布表单时,出现以下错误: 类型为TEST\MyBundle\Entity\Relation的实体通过具有标识 外部实体TEST\MyBundle\entity\Order,但此实体 本身没有标识。必须在上调用EntityManager#persist() 并确保生成了标识符 在尝试持久化“TEST\MyBundle\Entity\Relation”之前。如果 插入后ID生成(如MySQL自动增量或 这意味着您必须调用EntityManager#flush() 在两个持久化操作之间 我理解这个错误是因为条令试图持久化与顺序相关的Symfony 组合键和窗体,symfony,doctrine-orm,symfony-2.2,Symfony,Doctrine Orm,Symfony 2.2,我的数据库中有以下关联(简化版): 这是一个多对多关联,但在联接表上有一个属性,所以 我有一个表单,我可以在其中添加任意多个关系到一个订单项,并同时创建它(主要受文档中教程的启发) 当我发布表单时,出现以下错误: 类型为TEST\MyBundle\Entity\Relation的实体通过具有标识 外部实体TEST\MyBundle\entity\Order,但此实体 本身没有标识。必须在上调用EntityManager#persist() 并确保生成了标识符 在尝试持久化“TEST\MyBun
关系
对象,因为我在OneToMany
关系上有cascade={“persist”}
选项。但是我如何避免这种行为呢
我试图删除cascade={“persist”}
并手动持久化实体,但我得到了相同的错误(因为我需要flush()
才能获得ID,当我这样做时,我得到了相同的错误消息)。我还尝试在
flush()
之前detach()
分离关系
对象,但没有成功。您需要先保留并刷新原始对象,然后才能保留并刷新关系记录。错误原因100%正确
从图表中,我假设您正试图同时添加和排序以及与联系人的关系?如果是这样,您需要先保留和刷新订单,然后才能保留和刷新关系。或者您可以向关系表添加主键。我最终在我的
关系表上创建了一个单独的主键e(而不是复合的)。
这看起来像是一个肮脏的修复,我相信有更好的方法来处理这种情况,但它现在起作用
这是我的关系
实体:
/**
* Relation
*
* @ORM\Entity
*/
class Relation
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="Contact", inversedBy="relation")
*/
protected $contact;
/**
* @ORM\ManyToOne(targetEntity="Order", inversedBy="relation")
*/
protected $order;
/**
* @var integer
*
* @ORM\Column(name="invoice", type="integer", nullable=true)
*/
private $invoice;
//Rest of the entity...
然后,我在与Order
的OneToMany
关系中添加了cascade={“persist”}
选项:
/**
* Orders
*
* @ORM\Entity
*/
class Order
{
/**
* @ORM\OneToMany(targetEntity="Relation", mappedBy="order", cascade={"persist"})
*/
protected $relation;
//Rest of the entity...
Et voilá!如果1)您使用的是具有复合键的联接表,2)表单组件,以及3)联接表是由表单组件的“集合”字段生成的实体,则此问题似乎是唯一的。我看到很多人有问题,但没有很多解决方案,所以我想我应该分享我的
我希望保留我的复合主键,因为我希望确保只有两个外键的一个实例会保留在数据库中。使用
例如
/** @Entity */
class Order
{
/** @OneToMany(targetEntity="OrderItem", mappedBy="order") */
private $items;
public function __construct(Customer $customer)
{
$this->items = new Doctrine\Common\Collections\ArrayCollection();
}
}
/** @Entity */
class Product
{
/** @OneToMany(targetEntity="OrderItem", mappedBy="product") */
private $orders;
.....
public function __construct(Customer $customer)
{
$this->orders = new Doctrine\Common\Collections\ArrayCollection();
}
}
/** @Entity */
class OrderItem
{
/** @Id @ManyToOne(targetEntity="Order") */
private $order;
/** @Id @ManyToOne(targetEntity="Product") */
private $product;
/** @Column(type="integer") */
private $amount = 1;
}
我所面临的问题是,如果我在表单中构建一个集合字段为OrderItem
s的Order
对象,如果不先保存Order实体,我将无法保存OrderItem实体(因为doctor/SQL需要复合键的Order id),但是Doctrine EntityManager不允许我保存具有OrderItem属性的Order对象(因为它坚持将它们一起保存)。您不能关闭cascade,因为它会抱怨您没有首先保存关联的实体,并且您不能在保存订单之前保存关联的实体。真是个难题我的解决方案是删除关联的实体,保存Order
,然后将关联的实体重新引入Order对象并再次保存。首先,我创建了一个ArrayCollection属性的mass赋值函数$items
class Order
{
.....
public function setItemsArray(Doctrine\Common\Collections\ArrayCollection $itemsArray = null){
if(null){
$this->items->clear();
}else{
$this->items = $itemsArray;
}
....
}
然后在我的控制器中处理订单表单
//get entity manager
$em = $this->getDoctrine()->getManager();
//get order information (with items)
$order = $form->getData();
//pull out items array from order
$items = $order->getItems();
//clear the items from the order
$order->setItemsArray(null);
//persist and flush the Order object
$em->persist($order);
$em->flush();
//reintroduce the order items to the order object
$order->setItemsArray($items);
//persist and flush the Order object again ):
$em->persist($order);
$em->flush();
你必须坚持并冲洗两次,这太糟糕了(详见此处)。但这是你的信条,它的所有力量,它肯定会让你陷入困境。但谢天谢地,您只需在创建新对象时执行此操作,而不必进行编辑,因为该对象已在数据库中。您说得对,我正在尝试同时添加订单和与联系人的关系。我以前试图刷新顺序,但后来我得到一个错误,即需要一个级联={“persist”}
,如果我把它放回去,它会首先尝试保存关系。你在什么地方有工作的例子吗?我找不到一个…你需要手动保持关系。cascade={“persist”}
所做的一切就是,如果你将一个实体与该集合保持关系,它将自动添加$em->persist($relationshipObject)
,因此要解决你的问题,你需要关闭它,手动保持关系对象,并进行第二次刷新={“persist”}
然后首先persist/flush order对象,我得到一个:通过关系“TEST\MyBundle\entity\Orders\relations”找到了一个新实体,该关系没有配置为级联实体的persist操作:TEST\MyBundle\entity\relations…
。我甚至尝试使用detach()
在关系对象上,但未成功。。。