Как получить одномерный скалярный массив как результат доктрины dql-запроса?

Я хочу получить массив значений из столбца id таблицы аукциона. Если бы это был необработанный SQL, я бы написал:

SELECT id FROM auction

Но когда я делаю это в Доктрине и выполняю:

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

Я получаю такой массив:

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

Вместо этого я хотел бы получить такой массив:

array(
    1,
    2
)

Как я могу сделать это с помощью Doctrine?

Ответ 1

PHP < 5,5

Вы можете использовать array_map, и поскольку у вас есть только элемент на массив, вы можете элегантно использовать 'current' в качестве обратного вызова вместо записи закрытия.

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

См. Петр Соботка ниже для получения дополнительной информации об использовании памяти.

PHP >= 5.5

Как jcbwlkr ответил ниже, рекомендуется использовать его array_column.

Ответ 2

Начиная с PHP 5.5 вы можете использовать array_column для решения этой проблемы

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

Ответ 3

Лучшим решением является использование 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

Ответ 4

Ответ Аскариуса изящный, но остерегайтесь использования памяти! array_map() создает копию переданного массива и эффективно удваивает использование памяти. Если вы работаете с сотнями тысяч элементов массива, это может стать проблемой. Поскольку PHP 5.4 время вызова по ссылке удалено, поэтому вы не можете выполнять

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

В этом случае вы можете пойти с очевидным

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

Ответ 5

Я думаю, что это невозможно в Доктрине. Просто преобразуйте массив результатов в структуру данных, которую вы хотите, используя PHP:

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