Symfony3 / Doctrine2中$ em-> clear()时未定义的索引错误

时间:2017-01-20 09:02:30

标签: php doctrine-orm symfony

我收到此错误:

  

[Symfony的\元器件\调试\异常\ ContextErrorException]     注意:未定义索引:000000000fa82729000000006e17190b

我已尝试过this post的所有提示。

我的代码比其他海报的代码简单得多(询问这个问题)。

GradientStopCollection

为了告诉你,我已经尝试了上面链接中的建议,这里是带有实现提示的更复杂的代码(但结果仍然相同):

    $em = $this->getContainer()->get('doctrine')->getManager();
    $pictureUrlRepository = new ProductItemPictureUrlRepository($em);
    $pictures = $pictureUrlRepository->findAll();

    for ($i = 0; $i < 4; ++$i) {
        $productItem = $pictures[$i]->getProductItem();
        dump($productItem->getId());
        $fileName = 'file_' . $i;

        $productItemPicture = new ProductItemPicture();
        $productItemPicture->setProductItem($productItem);
        $productItemPicture->setFile($fileName);
        $productItemPicture->setPosition(1);
        $productItemPicture->setSize(1000);
        $productItemPicture->setWidth(1200);
        $productItemPicture->setHeight(1000);

        $em->persist($productItemPicture);
        $em->flush();
        $em->clear();
        unset($productItemPicture);
    }

当我评论(禁用)时,只有 $ em-&gt; clear();行,它的工作原理。没有运行clear()会有什么问题? 在进行数千个数据库条目而不是运行clear()时,我能得到什么?

2 个答案:

答案 0 :(得分:1)

一个基本问题是:

// Replace
$pictureUrlRepository = new ProductItemPictureUrlRepository($em);

// With
$pictureUrlRepository = $em->getRepository('AppBundle:ProductItemPictureUrl');

实体经理与其存储库之间存在复杂的关系。切勿尝试直接实例化存储库。幕后发生了很多事情。很惊讶你的发现甚至都有效。

当然,您似乎还添加了教条事件监听器?所以很难确切地说出问题的确切位置。如果存储库修复不起作用,则发布完整的堆栈跟踪。

你似乎也依赖于每件产品至少有四张图片,这有点危险。

============================

如果问题是通过存储库建议解决的,那么您的评论中并不是很清楚。但是在使用$ em-&gt;清除的同时你依赖于$ picture也有点危险。清除经理时,不知道实体发生了什么。所以把它们移到循环之外:

for ($i = 0; $i < 4; ++$i) {
    $em->persist($productItemPicture);
}
$em->flush();
$em->clear();

是的,我知道你处理大量物品时可能达到内存限制。 ORM在大批量作业方面不是很好。您可能需要下拉到使用DBAL连接对象。

答案 1 :(得分:1)

我发现我的问题是什么问题。

在开始迭代循环之前,我使用FindAll()方法获得所有结果。然后我通过引用该方法的数组结果来设置$ productItem。但是迭代周期中的clear()会破坏该数组中的实体ID。

当我查看Doctrine网站关于batch processing的网站示例时,我更关注clear()部分。但真正的问题是他们如何获得他们迭代的结果。他们在createQuery()结果上使用iterate()方法。

所以,更新后的代码,工作结果如下:

    $em = $this->getContainer()->get('doctrine')->getManager();
    $q = $em->createQuery('select p from AppBundle\Model\Product\Item\ProductItemPictureUrl p');
    $iterableResult = $q->iterate();

    $i = 0;
    foreach ($iterableResult as $row) {
        $productItem = $row[0]->getProductItem();
        dump($productItem->getId());
        $fileName = 'file_' . $i;

        $productItemPicture = new ProductItemPicture();
        $productItemPicture->setProductItem($productItem);
        $productItemPicture->setFile($fileName);
        $productItemPicture->setPosition(1);
        $productItemPicture->setSize(1000);
        $productItemPicture->setWidth(1200);
        $productItemPicture->setHeight(1000);

        $em->persist($productItemPicture);
        $em->flush();
        $em->clear();
        unset($productItemPicture);
        $i++;
    }

感谢@Cerad指导我这个方向。