Як отримати одновимірний скалярний масив як результат запиту dql?


116

Я хочу отримати масив значень із стовпця 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
)

Як я можу це зробити за допомогою доктрини?

Відповіді:


197

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.


9
getScalarResult () дасть вам рядки - використовуйте getArrayResult (), якщо хочете цілі числа
pHoutved

так! array_column () краще в управлінні пам’яттю чи це передбачливо, що ми маємо робити?
Dheeraj

151

З PHP 5.5 ви можете використовувати array_column для вирішення цього питання

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

98

Кращим рішенням є використання 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);
    }
}

Додайте його до Вчення:

$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


2
Я змінив це, щоб він підтримував indexBy gist.github.com/ostrolucky/f9f1e0b271357573fde55b7a2ba91a32
gadelat

18

Відповідь Аскарія - це елегантно, але остерігайтеся використання пам'яті! array_map()створює копію пройденого масиву і ефективно подвоює використання пам'яті. Якщо ви працюєте з сотнями тисяч елементів масиву, це може стати проблемою. Оскільки проходження часу виклику PHP 5.4 за посиланням було видалено, тому ви не можете цього робити

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

У такому випадку ви можете піти з очевидним

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

2
Це здавалося трохи протиінтуїтивним, оскільки наша мета - «майже скопіювати» масив в обох випадках. Мені довелося перевірити це, щоб переконатися, що це насправді: gist.github.com/PowerKiKi/9571aea8fa8d6160955f
PowerKiKi

4

Я думаю, що це неможливо в Доктрині. Просто перетворіть масив результатів у структуру даних, яку ви хочете використовувати за допомогою PHP:

$transform = function($item) {
    return $item['id'];
};
$result = array_map($transform, $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult());
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.