如何将一维标量数组作为Doctrine DQL查询结果获取?

137

我想从Auction表的id列中获取值数组。如果这是原始SQL,我会写:

SELECT id FROM auction

但是,当我在Doctrine中这样做并执行时:

$em->createQuery("SELECT a.id FROM Auction a")->getScalarResult(); 

我得到了这样一个数组:

array(
    array('id' => 1),
    array('id' => 2),
)

相反,我想要得到这样一个数组:

array(
    1,
    2
)

我该如何使用Doctrine来实现这个?

6个回答

210

PHP < 5.5

您可以使用array_map函数,并且由于每个数组只有一个项目,因此可以优雅地使用'current'作为回调而不是编写闭包

$result = $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
$ids = array_map('current', $result);

有关内存使用的其他信息,请参见Petr Sobotka的下面的回答

PHP >= 5.5

jcbwlkr在下面的回答中所说,建议使用array_column


15
如果您想要整数,请使用getArrayResult(),因为getScalarResult()会返回字符串。 - pHoutved
那么!array_column()在内存管理方面是否更好,还是使用foreach的方式更好,我们应该怎么做? - some_groceries

179
从PHP 5.5开始,你可以使用array_column来解决这个问题。
$result = $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
$ids = array_column($result, "id");

105
更好的解决方案是使用PDO:FETCH_COLUMN。为此,您需要一个自定义水合器:
//MyProject/Hydrators/ColumnHydrator.php
namespace DoctrineExtensions\Hydrators\Mysql;

use Doctrine\ORM\Internal\Hydration\AbstractHydrator, PDO;

class ColumnHydrator extends AbstractHydrator
{
    protected function hydrateAllData()
    {
        return $this->_stmt->fetchAll(PDO::FETCH_COLUMN);
    }
}

将其添加到Doctrine中:
$em->getConfiguration()->addCustomHydrationMode('COLUMN_HYDRATOR', 'MyProject\Hydrators\ColumnHydrator');

你可以像这样使用它:

$em->createQuery("SELECT a.id FROM Auction a")->getResult("COLUMN_HYDRATOR");

更多信息: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes


3
我已经修改了这个代码片段,使其支持indexBy功能。https://gist.github.com/ostrolucky/f9f1e0b271357573fde55b7a2ba91a32 - gadelat

18

Ascarius的答案很优雅,但要注意内存使用!array_map()会创建一个传递数组的副本并有效地使内存使用量翻倍。如果您处理数十万个数组项,则可能会成为问题。自PHP 5.4起,已删除了按引用传递调用时间,因此您不能执行以下操作

// note the ampersand
$ids = array_map('current', &$result);

在这种情况下,你可以选择显而易见的选择。

$ids = array();
foreach($result as $item) {
  $ids[] = $item['id'];
}

2
这似乎有点违反直觉,因为我们的目标是在两种情况下“几乎复制”数组。我不得不亲自测试才能确信它实际上是真的:https://gist.github.com/PowerKiKi/9571aea8fa8d6160955f - PowerKiKi

16

在使用查询构建器时,我必须定义我想要返回的列:$queryBuilder = $this->createQueryBuilder('a'); // ... 构建查询 $resultMapping = new Query\ResultSetMapping(); $resultMapping->addScalarResult('id', 'id', 'integer'); return $query->getQuery()>setResultSetMapping($resultMapping)->getSingleColumnResult(); - Orlando

4

我认为在Doctrine中这是不可能的。只需要使用PHP将结果数组转换成所需的数据结构即可:

$transform = function($item) {
    return $item['id'];
};
$result = array_map($transform, $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接