web-dev-qa-db-fra.com

Comment obtenir un tableau scalaire unidimensionnel sous la forme d'un résultat de requête doctrine dql?

Je souhaite obtenir un tableau de valeurs de la colonne id du tableau Auction. Si c'était un SQL brut, j'écrirais:

SELECT id FROM auction

Mais quand je fais cela dans Doctrine et exécuter:

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

Je reçois un tableau comme celui-ci:

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

Au lieu de cela, je voudrais obtenir un tableau comme celui-ci:

array(
    1,
    2
)

Comment puis-je faire cela en utilisant Doctrine?

100
Dawid Ohia

PHP <5.5

Vous pouvez utiliser array_map, et comme vous n’avez qu’un élément par tableau, vous pouvez utiliser élégamment 'current' comme rappel, au lieu d’écrire un fermeture .

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

Voir réponse de Petr Sobotka ci-dessous pour plus d'informations sur l'utilisation de la mémoire.

PHP> = 5.5

Comme les réponses de jcbwlkr ci-dessous , il est recommandé d'utiliser array_column.

184
Lionel Gaillard

À partir de PHP 5.5, vous pouvez utiliser array_column pour résoudre ceci

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

Une meilleure solution consiste à utiliser PDO:FETCH_COLUMN. Pour ce faire, vous avez besoin d'un hydrateur personnalisé:

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

Ajoutez-le à la doctrine:

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

Et vous pouvez l'utiliser comme ceci:

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

Plus d'infos: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes

89
Ioan Badila

La réponse d'Ascarius est élégante, mais méfiez-vous de l'utilisation de la mémoire! array_map() crée une copie du tableau transmis et double efficacement l'utilisation de la mémoire. Si vous travaillez avec des centaines de milliers d'éléments de tableau, cela peut devenir un problème. Depuis PHP 5.4, le passage par référence a été supprimé afin que vous ne puissiez pas faire

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

Dans ce cas, vous pouvez aller avec évident

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

Je pense que c'est impossible dans Doctrine. Il vous suffit de transformer le tableau de résultats en structure de données que vous souhaitez utiliser avec PHP:

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