140

I want to get an array of values from the id column of the Auction table. If this was a raw SQL I would write:

SELECT id FROM auction 

But when I do this in Doctrine and execute:

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

I get an array like this:

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

Instead, i'd like to get an array like this:

array( 1, 2 ) 

How can I do that using Doctrine?

6 Answers 6

210

PHP < 5.5

You can use array_map, and since you only have on item per array, you can elegantly use 'current' as callback, instead of writing a closure.

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

See Petr Sobotka's answer below for additional info regarding memory usage.

PHP >= 5.5

As jcbwlkr's answered below, the recommended way it to use array_column.

Sign up to request clarification or add additional context in comments.

2 Comments

getScalarResult() will give you strings - use getArrayResult() if you want integers
so! is array_column() better at memory management or is it the foreach way, what shoud we do?
180

As of PHP 5.5 you can use array_column to solve this

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

Comments

105

A better solution is to use PDO:FETCH_COLUMN . To do so you need a custom hydrator:

//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); } } 

Add it to Doctrine:

$em->getConfiguration()->addCustomHydrationMode('COLUMN_HYDRATOR', 'MyProject\Hydrators\ColumnHydrator'); 

And you can use it like this:

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

More info: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes

1 Comment

I've modified this so it supports indexBy gist.github.com/ostrolucky/f9f1e0b271357573fde55b7a2ba91a32
21

Since doctrine/orm 2.10.0 there is a built-in solution for this:

use Doctrine\ORM\AbstractQuery; $query = $em->createQuery("SELECT a.id FROM Auction a"); return $query->getSingleColumnResult(); // Same as: return $query->getResult(AbstractQuery::HYDRATE_SCALAR_COLUMN); 

Docs: https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/dql-doctrine-query-language.html#scalar-column-hydration

1 Comment

When using query builder, I had to define the column that I wanted to have returned: ``` $queryBuilder = $this->createQueryBuilder('a'); // ... Build the query $resultMapping = new Query\ResultSetMapping(); $resultMapping->addScalarResult('id', 'id', 'integer'); return $query->getQuery()>setResultSetMapping($resultMapping)->getSingleColumnResult(); ```
18

Ascarius' answer is elegant, but beware of memory usage! array_map() creates a copy of passed array and effectively doubles memory usage. If you work with hundreds of thousands of array items this can become an issue. Since PHP 5.4 call-time pass by reference has been removed so you cannot do

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

In that case you can go with obvious

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

1 Comment

That seemed a bit counter-intuitive, since our goal is to "almost copy" the array in both cases. I had to test it myself to be convinced it is actually true: gist.github.com/PowerKiKi/9571aea8fa8d6160955f
4

I think it's impossible in Doctrine. Just transform result array into the data structure you want using PHP:

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.