Есть ли способ получить ассоциативный массив, сгруппированный по значениям указанного столбца с PDO?

Например, давайте использовать некоторый простой набор данных

+---------+------+------+------------+ | name | age | sex | position | +---------+------+------+------------+ | Antony | 34 | M | programmer | | Sally | 30 | F | manager | | Matthew | 28 | M | designer | +---------+------+------+------------+ 

Мы пытаемся получить массив, организованный таким образом

 Array ( [Antony] => Array ( [age] => 34 [sex] => M [position] => programmer ) [Sally] => Array ( [age] => 30 [sex] => F [position] => manager ) [Matthew] => Array ( [age] => 28 [sex] => M [position] => designer ) ) 

В грубом приближении мы можем использовать

 $pdo->query('SELECT * FROM employee')->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC); 

Но в результате у нас есть ненужный уровень гнездования

 Array ( [Antony] => Array ( [0] => Array ( [age] => 34 [sex] => M [position] => programmer ) ) [Sally] => Array ( [0] => Array ( [age] => 30 [sex] => F [position] => manager ) ) [Matthew] => Array ( [0] => Array ( [age] => 28 [sex] => M [position] => designer ) ) ) 

Я попытался избавиться от этого ненужного уровня вложенности, используя функцию обратного вызова

 $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC|PDO::FETCH_FUNC, 'current'); 

Но по некоторым причинам он не проходит

 Array ( [0] => Array ( [age] => 34 [sex] => M [position] => programmer ) ) 

а просто кучу скаляров 34, 'M', 'programmer' для функции обратного вызова 🙁

Вы можете видеть это, используя такую ​​функцию, как обратный вызов

 function what_do_you_pass_me() { $numargs = func_num_args(); $arg_list = func_get_args(); for ($i = 0; $i < $numargs; $i++) { echo "Argument $i is: " . $arg_list[$i] . "\n"; }; echo "\n\n"; }; 

Итак, есть способ получить желаемый результат с использованием режимов PDO::FETCH_* без использования array_map('current', $result) после получения результатов?

Это довольно старая тема, но я нашел очень легкое решение:

 ->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE) 

Первый col будет установлен как ключ, остальные будут установлены как значение.

Не нужно ходить по массиву или использовать array_map.

для уменьшения ненужного уровня массива вложенности:

 $res = $pdo->query('SELECT * FROM employee')->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC); $res = array_map('reset', $res); 

Массив ключей

 PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC 

Этот ответ устарел, пожалуйста, см. Другой ответ .


Похоже, что нет никакого способа сделать это как часть fetchAll .

Лучше всего будет создавать класс, который расширяет PDO, добавляя к нему полезный метод.

 public function queryKeyedAssoc($query, $params, $key) { $sth = $this->prepare($query); $sth->execute($params); $res = array(); while($row = $sth->fetch(PDO::FETCH_ASSOC)) $res[ $row[$key] ] = $row; return $res; } 

Мы можем сделать решение Чарльза немного лучше, расширив класс операторов:

 class MyPdo extends PDO { function __construct($host, $database_name, $username, $password, $options=array()) { $options = self::merge(array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_STATEMENT_CLASS => array('PdoPlusStatement', array()), PDO::ATTR_EMULATE_PREPARES => true, PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', ), $options); $dsn = "mysql:host=$host;dbname=$database_name;charset=utf8"; parent::__construct($dsn, $username, $password, $options); } } class PdoPlusStatement extends PDOStatement { protected function __construct() {} /** * @param array|mixed $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed, or one or more non-array arguments to be matched with sequential parameter markers. * @throws PDOException * @return PdoPlusStatement */ public function execute($input_parameters=null) { $args = func_get_args(); $argc = func_num_args(); if($argc===0) { parent::execute(); } else { if($argc===1 && is_array($args[0])) { $args = $args[0]; } parent::execute($args); } return $this; } /** * Returns an array containing all of the remaining rows in the result set * @return array An associative array using the first column as the key, and the remainder as associative values */ public function fetchKeyAssoc() { return array_map('reset', $this->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC)); } } 

Применение:

 $users = $pcs->query("SELECT name, user_id, discipline_id FROM wx_user")->fetchKeyAssoc();