Symfony3 / Doctrine2 中 $em->clear() 时出现未定义索引错误
Posted
技术标签:
【中文标题】Symfony3 / Doctrine2 中 $em->clear() 时出现未定义索引错误【英文标题】:Undefined index error when $em->clear() in Symfony3 / Doctrine2 【发布时间】:2017-01-20 09:02:29 【问题描述】:我收到此错误:
[Symfony\Component\Debug\Exception\ContextErrorException] 注意:未定义索引:000000000fa82729000000006e17190b
我已经尝试了this post的所有提示。
我的代码比其他发帖者的代码简单多了(问这个问题)。
$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 = $this->getContainer()->get('doctrine')->getManager();
$pictureUrlRepository = new ProductItemPictureUrlRepository($em);
$pictures = $pictureUrlRepository->findAll();
foreach ($em->getEventManager()->getListeners() as $event => $listeners)
foreach ($listeners as $listener)
$em->getEventManager()->removeEventListener($event, $listener);
$batchSize = 2;
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);
$productItemPicture->setCreated(new \DateTime('20.1.2017'));
$productItemPicture->setUpdated(new \DateTime('20.1.2017'));
$em->persist($productItemPicture);
if (($i % $batchSize) === 0)
$em->flush();
$em->clear();
$em->flush();
$em->clear();
仅当我评论(禁用)$em->clear();行,它的工作原理。不运行 clear() 有什么问题? 在执行数千个数据库条目但不运行 clear() 时会发生什么?
【问题讨论】:
能否请您标记出此错误的“行”?也许来自你在循环之后执行的代码? 当我评论 $em->clear();有用。所以这是行。 你有多少张照片? 5?少一点? 也许,但您正在清除EntityManager
,如果您在循环后尝试更新其他实体,这将引发您提供的异常。
@Veve 我有数千张图片,但为了测试,我减少到 4 张,以表明它仍然会导致这个问题。涉及此问题的其他线程与内存泄漏有关,因此我将此测试缩减为 4,以触发此错误。
【参考方案1】:
我发现了我的问题所在。
在开始迭代循环之前,我使用 FindAll() 方法获得所有结果。然后我通过引用该方法的数组结果来设置 $productItem。但是迭代周期中的 clear() 会破坏该数组中的实体 ID。
当我查看有关 batch processing 的 Doctrine 网站示例时,我更关心 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 为我指明了这个方向。
【讨论】:
作为参考,我找到了这个主题,这不是完全相同的问题,但为这个问题带来了一些启示:***.com/questions/7431794/…【参考方案2】:一个基本问题是:
// Replace
$pictureUrlRepository = new ProductItemPictureUrlRepository($em);
// With
$pictureUrlRepository = $em->getRepository('AppBundle:ProductItemPictureUrl');
实体管理器与其存储库之间存在复杂的关系。永远不要尝试直接实例化存储库。很多事情在幕后发生。很惊讶您的 findAll 甚至可以正常工作。
当然,您似乎也添加了学说事件侦听器?所以很难说问题出在哪里。如果存储库修复不起作用,请发布完整的堆栈跟踪。
您似乎还依赖于每个产品至少有四张图片,这有点危险。
=============================
如果问题已通过存储库建议解决,您的 cmets 并不清楚。但是在依赖 $pictures 的同时使用 $em->clear 也有点危险。当您清除经理时,不知道实体发生了什么。所以将它们移到循环之外:
for ($i = 0; $i < 4; ++$i)
$em->persist($productItemPicture);
$em->flush();
$em->clear();
是的,我知道您在处理大量项目时可能会达到内存限制。 ORM 不太擅长大批量作业。您可能需要下拉以使用 DBAL 连接对象。
【讨论】:
感谢您的关注。我理解您对存储库的“新”部分的担忧。我是 Symfony 的新手,我添加这个“新”部分只是因为在这里将代码发布到 ***。原因是,我在项目的其他部分发现了类似的代码,由其他程序员编写并且代码有效。所以,我自己使用的是这个代码 $doctrine->getRepository(ProductItemPictureUrl::class) 我希望和你发布的一样。 我没有使用事件监听器。在我的第二个代码示例中,我取消注册它们只是因为其他线程中的先前答案建议了这一点,以防存在一些内部侦听器。 在我的生产代码中,依赖图片的数量也是不正确的。此实际功能仅用于测试目的,以跟踪此错误。 我不知道如何获取此错误的堆栈跟踪,如何获取比简单的“通知:未定义索引”消息更多的信息。 感谢您的回答。存储库建议没有解决问题,它的工作原理相同。当我将 flush() 和 clear() 放在循环之外时,它工作正常。完全不使用 clear() 也是如此。有趣的是,当我运行我的原始代码时,在循环内使用 clear() 时,总是有 1 个项目插入到 DB 表中。 clear() 不会直接导致错误。我想只有在再次使用 $em 之后(在第一次 clear() 之后),它才会导致错误。因此,当我将 clear() 移到循环之外时,它不会触发任何错误,因为我的脚本在那里结束。以上是关于Symfony3 / Doctrine2 中 $em->clear() 时出现未定义索引错误的主要内容,如果未能解决你的问题,请参考以下文章