Есть ли способ получить ассоциативный массив, сгруппированный по значениям указанного столбца с 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)
после получения результатов?
Ответы
Ответ 1
Это довольно старая тема, но я нашел очень легкое решение:
->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE)
Первый столбец будет установлен как ключ, остальные будут установлены как значение.
Не нужно ходить по массиву или использовать array_map.
Ответ 2
чтобы уменьшить ненужный уровень массива вложенности:
$res = $pdo->query('SELECT * FROM employee')->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
$res = array_map('reset', $res);
Ответ 3
Ключ-массив
PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC
Ответ 4
Этот ответ устарел, см. этот другой ответ.
Похоже, что нет возможности сделать это как часть 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;
}
Ответ 5
Мы можем сделать решение Чарльза немного лучше, расширив класс операторов:
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();