有没有办法获取按 PDO 指定列的值分组的关联数组?

2022-08-30 14:42:02

例如,让我们使用一些简单的数据集

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

被接受的答案本质上是一个货物崇拜代码,它只是偶然地完成了它的工作,但本身就没有意义。

PDO::FETCH_GROUPPDO::FETCH_UNIQUE是相互排除的获取模式,不能一起使用。其中只有一个会起作用。当您将它们组合在一起时,后者将接管并且实际上只是.\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUEPDO::FETCH_UNIQUE

除此之外,这个问题本身是模棱两可的,OP希望他的数组被唯一字段索引,而他称之为分组,这也在答案中引起了争议。

因此,要直截了当:

  • 要为具有唯一值的数组编制索引(当您希望按员工的姓名对结果数组进行索引时,假设它们是唯一的),提取模式必须是 PDO::FETCH_UNIQUE

    $pdo->query('SELECT name, e.* FROM employee e')->fetchAll(PDO::FETCH_UNIQUE);
    
  • 要对结果进行分组(例如,当您要按部门对员工进行分组时),提取模式必须为 PDO::FETCH_GROUP

    $pdo->query('SELECT dept_id, e.* FROM employee e')->fetchAll(PDO::FETCH_GROUP);
    

在这两种情况下,要用作第一级数组索引的字段都必须首先列在 SELECT 字段列表中。

有关 的注释。鉴于可以在构造函数中为所有结果格式设置一次首选结果格式的提取模式,因此显式列出它是没有意义的。PDO::FETCH_ASSOC