我收到这个错误:
[Symfony\Component\Debug\Exception\ContextErrorException]注意:未定义索引:000000000 fa82729000000006e17190b
我已经尝试了这篇文章中的所有技巧。
我的代码比其他海报的代码要简单得多(询问这个问题)。
$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()有什么用当我做了数千个DB条目而不运行clear()时,我能期待什么
我发现了我的案例中的问题所在。
在开始itearation循环之前,我使用FindAll()方法获得所有结果。然后,我通过引用该方法的数组结果来设置$productItem。但是迭代周期中的clear()会破坏该数组中的实体ID。
当我查看Doctrine网站上关于批处理的示例时,我更关心clear()部分。但真正的问题是他们如何得到迭代的结果。他们对createQuery()结果使用iterate()方法。
所以,更新后的代码,工作结果是这样的:
$em = $this->getContainer()->get('doctrine')->getManager();
$q = $em->createQuery('select p from AppBundleModelProductItemProductItemPictureUrl 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为我指明了这个方向。
一个基本问题是:
// Replace
$pictureUrlRepository = new ProductItemPictureUrlRepository($em);
// With
$pictureUrlRepository = $em->getRepository('AppBundle:ProductItemPictureUrl');
实体管理器和它的存储库之间存在着复杂的关系。永远不要尝试直接实例化存储库。幕后发生了很多事情。很惊讶你的发现一切都奏效了。
当然,你似乎也增加了教条事件的听众?所以很难说问题到底出在哪里。如果存储库修复不起作用,那么发布完整的堆栈跟踪。
你似乎还依赖于每个产品至少有四张照片,这有点危险。
==============================
从您的评论中并不清楚问题是否通过存储库建议得到了解决。但是在依赖$pictures的同时使用$em->clear也有点危险。当你清除经理时,不知道实体发生了什么。所以把它们移出循环:
for ($i = 0; $i < 4; ++$i) {
$em->persist($productItemPicture);
}
$em->flush();
$em->clear();
是的,我知道当你处理大量项目时,你可能已经达到了内存限制。ORM不太擅长大批量作业。您可能需要下拉到使用DBAL连接对象。