Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 508
HongKilDong Avatar asked Mar 19 '11 11:03

HongKilDong


People also ask

How to fetch array in php PDO?

PDOStatement::fetchAll() returns an array containing all of the remaining rows in the result set. The array represents each row as either an array of column values or an object with properties corresponding to each column name. An empty array is returned if there are zero results to fetch.

How to use fetchAll php?

Using the PHP fetchAll() method with the query() method If a query doesn't accept a parameter, you can fetch all rows from the result set as follows: First, execute the query by calling the query() method of the PDO object. Then, fetch all rows from the result set into an array using the fetchAll() method.

What is the default data type for the fetchAll () result?

By default, user-missing values are converted to the Python data type None.


2 Answers

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.

like image 87
imclickingmaniac Avatar answered Sep 21 '22 02:09

imclickingmaniac


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.

like image 44
Your Common Sense Avatar answered Sep 22 '22 02:09

Your Common Sense