For example, let\'s use some simple data set
+---------+------+------+------------+
| name | age | sex | position |
+---------+------+------+---------
This answer is out of date, please see this other answer instead.
It looks like there's no way to do this as part of fetchAll
.
Your best bet is going to be creating a class that extends PDO, adding a utility method to it.
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;
}
We can make Charles' solution a little nicer by extending the statement class instead:
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));
}
}
Usage:
$users = $pcs->query("SELECT name, user_id, discipline_id FROM wx_user")->fetchKeyAssoc();
Not sure why no one has posted the following solution, but it works perfectly for me:
PDO::FETCH_UNIQUE | PDO::FETCH_ASSOC
So, changing your statement to:
$pdo->query('SELECT * FROM employee')->fetchAll(PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC);
should be exactly what you want.
It's quite old topic, but I found very easy solution:
->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE)
First col will be set as key, rest will be set as value.
No need to walk over the array or use array_map.
The accepted answer is essentially a cargo cult code, that does its job only by accident, but makes no sense by itself.
PDO::FETCH_GROUP
and PDO::FETCH_UNIQUE
are mutual exclusive fetch modes, that cannot be used together. Only one of them would work. When you combine them, the latter takes over and \PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE
is actually just PDO::FETCH_UNIQUE
.
Beside that, the question is ambiguous by itself, the OP wants his array to be indexed by the unique field, whereas he called it grouping which raised a controversy in the answers as well.
So to make it straight:
to index an array with unique values (when you want the resulting array to be indexed by the employee's name, given they are unique), the fetch mode must be PDO::FETCH_UNIQUE:
$pdo->query('SELECT name, e.* FROM employee e')->fetchAll(PDO::FETCH_UNIQUE);
to group the results (when you want to group employees by department, for example), the fetch mode must be PDO::FETCH_GROUP:
$pdo->query('SELECT dept_id, e.* FROM employee e')->fetchAll(PDO::FETCH_GROUP);
in both cases the field to be used as the first level array index, must be listed first in the SELECT field list.
A note on the PDO::FETCH_ASSOC
. Given that fetch mode for the preferred result format could be set once for all in the constructor, it makes no sense to list it explicitly as well.
to reduce a unnecessary nesting array level:
$res = $pdo->query('SELECT * FROM employee')->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
$res = array_map('reset', $res);