Как получить одномерный скалярный массив как результат доктрины 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());