【问题标题】:Undefined index error when $em->clear() in Symfony3 / Doctrine2Symfony3 / Doctrine2 中 $em->clear() 时出现未定义索引错误
【发布时间】: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,以触发此错误。

标签: php doctrine-orm symfony


【解决方案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 为我指明了这个方向。

【讨论】:

【解决方案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 的新手,我添加这个“新”部分只是因为在这里将代码发布到 Stackoverflow。原因是,我在项目的其他部分发现了类似的代码,由其他程序员编写并且代码有效。所以,我自己使用的是这个代码 $doctrine->getRepository(ProductItemPictureUrl::class) 我希望和你发布的一样。
  • 我没有使用事件监听器。在我的第二个代码示例中,我取消注册它们只是因为其他线程中的先前答案建议了这一点,以防存在一些内部侦听器。
  • 在我的生产代码中,依赖图片的数量也是不正确的。此实际功能仅用于测试目的,以跟踪此错误。
  • 我不知道如何获取此错误的堆栈跟踪,如何获取比简单的“通知:未定义索引”消息更多的信息。
  • 感谢您的回答。存储库建议没有解决问题,它的工作原理相同。当我将 flush() 和 clear() 放在循环之外时,它工作正常。完全不使用 clear() 也是如此。有趣的是,当我运行我的原始代码时,在循环内使用 clear() 时,总是有 1 个项目插入到 DB 表中。 clear() 不会直接导致错误。我想只有在再次使用 $em 之后(在第一次 clear() 之后),它才会导致错误。因此,当我将 clear() 移到循环之外时,它不会触发任何错误,因为我的脚本在那里结束。
猜你喜欢
  • 2023-04-05
  • 2016-12-25
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
  • 2011-03-16
  • 2020-12-03
  • 2015-11-12
相关资源
最近更新 更多