Symfony 一对一的关系不会随着新的实体而持续
当我试图使用symfony表单持久化实体集合时,我面临一些问题。我遵循了以下步骤,但由于以下错误,我无法使其正常工作:Symfony 一对一的关系不会随着新的实体而持续,symfony,doctrine-orm,Symfony,Doctrine Orm,当我试图使用symfony表单持久化实体集合时,我面临一些问题。我遵循了以下步骤,但由于以下错误,我无法使其正常工作: Entity of type ProductItem has identity through a foreign entity Product, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and
Entity of type ProductItem has identity through a
foreign entity Product, however this entity has no identity itself. You have to call
EntityManager#persist() on the related entity and make sure that an identifier was
generated before trying to persist ProductItem. In case of Post Insert ID
Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you
have to call EntityManager#flush() between both persist operations.
我必须联系与一家公司有关系的实体:
产品
/**
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @ORM\OneToMany(targetEntity="ProductItem", mappedBy="product",cascade={"persist"})
*/
protected $items;
和产品项
/**
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="Product", inversedBy="items")
*/
protected $product;
/**
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="Item")
*/
protected $item;
以下是如何将其添加到表单中:
->add('items','collection',array(
'label' => false,
'type' => new ProductItemType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false))
这是控制器的动作:
public function newAction()
{
$product= new Product();
$form = $this->createForm(new ProductType(), $product);
if($request->isMethod("POST"))
{
$form->handleRequest($request);
if($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
}
}
}
我在控制器中肯定做错了什么,因为正如错误消息所说,我必须在添加$productItems之前保留$product,但我如何才能做到这一点?
我仅在尝试持久化新实体时出现此错误,如果该实体以前已被持久化,我可以根据需要成功添加项目您没有完全遵循文档。下面是测试单个
项目的一些方法,但是如果您想动态添加和删除项目(看起来是这样),您还需要实现链接到的文档中包含的所有javascript
$product= new Product();
$productItem = new ProductItem();
// $items must be an arraycollection
$product->getItems()->add($productItem);
$form = $this->createForm(new ProductType(), $product);
if($request->isMethod("POST"))
{
$form->handleRequest($request);
if($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($productItem);
$em->persist($product);
$em->flush();
}
}
所以这应该适用于单个静态项
,但正如我所说的,动态内容需要做更多的工作。注释是错误的。。。这种关系是错误的
/**
* @ORM\OneToMany(targetEntity="ProductItem", mappedBy="product")
*/
protected $items;
/**
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="Product", inversedBy="items", cascade={"persist"})
*/
protected $product;
实现这一点的另一种方法(例如,不可能进行注释)是设置表单。在IMO中,您的问题与控制器无关,而是与实体相关。似乎您希望在产品和项目之间创建一个多个对象,而不是创建一个ProductItem类,该类应作为表示关系的中间对象。此外,此中间对象没有id生成策略。这就是为什么Doctrine向您解释,您必须先持久化/刷新所有新项目,然后持久化/刷新产品,以便能够获取中间对象的ID。上周我遇到了完全相同的问题,下面是我在阅读和测试后发现的解决方案
问题是您的产品实体具有级联持久化(这通常是好的),它首先尝试持久化ProductItem
,但是ProductItem
实体无法持久化,因为它们需要首先持久化产品及其ID(复合键(产品,项目))
有两个选项可以解决此问题:
1st我没有使用它,但是您可以简单地删除一个复合键,然后使用带有外键的标准id来访问产品
2nd-更好这看起来像是黑客攻击,但请相信我,这是您现在能做的最好的事情。它不需要对数据库结构进行任何更改,并且可以毫无问题地处理表单集合
我的代码中的代码片段,文章部分的复合键为(article_id,random_hash)。临时将一对多引用设置为空数组,将其持久化,添加原始数据并再次持久化(和刷新)
在使用CollectionType字段所附表单的过程中,也遇到了这个问题。可以解决这个问题的另一种方法,也在条令官方文件中提到,如下所示:
public function newAction()
{
$product= new Product();
$form = $this->createForm(new ProductType(), $product);
if($request->isMethod("POST"))
{
$form->handleRequest($request);
if($form->isValid())
{
foreach ($product->getItems() as $item)
{
$item->setProduct($product);
}
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
}
}
}
简单地说,您应该手动提供链接项目的产品链接-这在“建立关联”中有描述以下文章的一节:也许您忘记了在ProductItem
或Product
上添加注释@ORM\Entity,我已经实现了javascript,并在编辑操作中添加/删除了productItems(一旦创建了产品)。我的问题是,当我尝试持久化ProductItem集合时,会抛出一个异常,因为新产品尚未持久化。我不知道的是如何先持久化产品,然后持久化ProductItem集合以避免该异常。现在我收到此错误`通过关系Product#items找到了一个新实体未配置为级联实体:Test的持久化操作。若要解决此问题,请对此未知实体显式调用EntityManager#persist(),或在映射中配置级联持久化此关联,例如@manytone(..,cascade={“persist”}).
当然,这两个实体之间应该有很多,但我需要在它们的关系中添加一些值,这就是我使用OneToMany的原因。我一直在寻找一些关于如何处理这种情况的教程,但我没有找到任何东西。也许我需要尝试一种不同的方法…谢谢!非常有效,这不是最干净的方法,但它是e一个有效的。谢谢!!
public function newAction()
{
$product= new Product();
$form = $this->createForm(new ProductType(), $product);
if($request->isMethod("POST"))
{
$form->handleRequest($request);
if($form->isValid())
{
foreach ($product->getItems() as $item)
{
$item->setProduct($product);
}
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
}
}
}