Categories
arrays fetch pdo php

Is there a way to fetch associative array grouped by the values of a specified column with PDO?

For example, let’s use some simple data set

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

What we are trying to get is array organized this way

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
)
)

As a rough approximation we can use

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

But as result we have unnecessary nesting level

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
)
)
)

I tried to get rid of this unnecessary nesting level by using callback function

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

But for some reasons It passes not

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

but just a bunch of scalars 34, 'M', 'programmer' to callback function 🙁

You can see it using such function as callback

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";
};

So is there a way to get desired resultset using PDO::FETCH_* modes without using array_map('current', $result) after fetching results ?

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.