4

我对 Doctrine 很陌生,所以对于那些更有经验的人来说,这似乎是一个相当明显的问题。

我正在编写一个数据导入工具,它必须检查导入的每一行是否包含有效数据。例如,Row 引用了产品代码,我需要检查该代码是否存在预先存在的 Product 对象。如果不是,则将该行标记为无效。

现在我可以很容易地为每一行做这样的事情。

$productCode = $this->csv->getProductNumber();
$product = $doctrine->getRepository('MyBundle:Product')->findOneBy(array('code' => $productCode ));

但这似乎效率低得可怕。所以我考虑返回整个产品集合,然后在其中进行迭代。

$query = $this->getEntityManager()->createQuery('SELECT p FROM MyBundle\Entity\Product p');
$products = $query->getResult();

一切都很好,但是我必须编写混乱的循环来搜索。

两个问题:

1)。我想知道我是否遗漏了一些实用方法,例如 Magento Collections 中的一些实用方法,您可以在其中搜索 Collection 结果,而不会产生额外的数据库命中。例如,在 Magento 中,这将在 code 属性上迭代集合和过滤器。

$collection->getItemByColumnValue("code","FZTY444");

2)。目前我正在使用下面的查询,它返回一个“矩形数组”。效率更高,但可能会更好。

$query = $this->getEntityManager()->createQuery('SELECT p.code FROM MyBundle\Entity\Product p');
$products = $query->getResult();

有没有一种方法可以返回一维数组而不必重复结果集并转换为平面数组,所以我可以在结果上使用 in_array() ?

4

2 回答 2

7

如果我正确理解您的问题,您想要过滤由 getResult() 返回的实体数组。我有一个类似的问题,我想我已经想出了两种方法。

方法一:数组

对变量使用array_filter方法。$products是的,这相当于背景中的“循环”,但我认为这是一种通常可以接受的过滤数组的方式,而不是自己编写。您需要提供回调(首选 5.3 中的匿名函数)。这是一个例子

$codes = array_filter($products, function($i) {
    return $i->getCode() == '1234';
});

基本上在您的函数中,如果您希望返回结果,则返回 true,$codes否则返回 false(不确定是否需要 false,或者 void 返回值是否足够)。

方法二:Doctrine 的 ArrayCollection

在您的自定义存储库或任何您返回 getResult() 方法的地方,您可以改为返回 ArrayCollection。这可以在 Doctrine 命名空间中找到Doctrine\Common\Collections\。有关此方法背后的接口的更多文档可以在这里找到。所以在这种情况下你会有

$query = $this->getEntityManager()->createQuery('SELECT p FROM MyBundle\Entity\Product p');
$products = new ArrayCollection($query->getResult());

然后,您可以在数组集合上使用 filter() 方法。以与 array_filter 非常相似的方式使用它。除了它不需要第一个参数,因为你这样称呼它:$products->filter(function($i) { ... });

ArrayCollection 类是一个迭代器,因此您可以在foreach循环中使用它来满足您的需求,并且它与您的产品数组应该没有什么不同。除非您的代码明确使用$products[$x],否则它应该是即插即用*。

*注意:我还没有实际测试过这个代码或概念,但根据我读过的所有内容,它似乎是合法的。如果事实证明我错了,我会更新我的答案。

于 2012-11-13T16:16:24.437 回答
0

您可以使用另一种补水模式。$query->getResult() 通常返回对象水合的结果。看看$query->getScalarResult(),应该更适合你的需求。

更多信息请访问Doctrine 2 网站

于 2012-06-14T17:22:08.080 回答