Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Symfony 一对一的关系不会随着新的实体而持续_Symfony_Doctrine Orm - Fatal编程技术网

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

当我试图使用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 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();
        }
    }
}