PDOStatement:在“fetchAll($mode);”和“setFetchMode($mode)之间得到不同的


PDOStatement: Getting different results between `fetchAll($mode);` and `setFetchMode($mode); fetchAll();`

我有一个关于PDO的问题。

两者之间有区别吗

$sql = "SELECT * FROM pages";
$pdo = $this->db->query($sql);
$result = $pdo->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC); 

$sql = "SELECT * FROM pages";
$pdo = $this->db->query($sql);
$pdo->setFetchMode(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
$result = $pdo->fetchAll();

我为他们每个人得到不同的$result

PHP 中关于这些获取模式的文档对我来说不是很清楚。

我有一个包含不同页面的表,我想获取按其 ID 索引的所有页面。

第一种方法返回以下内容:

[
   [id of page 1] => [
      [0] => [ page 1 ],
   ],
   [id of page 2] => [
      [0] => [ page 2 ],
   ],
   ...
]

当我做第二种方法时,我只得到:

[
   [0] => [ page 1 ],
   [1] => [ page 2 ],
   [3] => [ page 3 ],
   ...
]

我想要这样:

[
   [id of page 1] => [ page 1 ],
   [id of page 2] => [ page 2 ],
   [id of page 3] => [ page 3 ],
   ...
]

第一个对我来说已经足够了,因为我可以使用数组映射函数轻松调整它:

array_map('reset', $result);

解释似乎是fetchAll()setFetchMode()支持不同的PDO::FETCH__常量集。

我认为setFetchMode()忽略了PDO::FETCH_GROUP,但不是PDO::FETCH_ASSOC.

我从 PHP 源代码中确认了这一点,请参阅setFetchMode()实现。setFetchMode支持的常量列表不包括PDO::FETCH_GROUP


为什么setFetchMode()fetchAll()的结果不同

代码:

<?php
$db = new PDO('mysql:host=localhost;dbname=test', 'root');
// print the default output, no constants
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$result = $q->fetchAll();
echo 'Result 0' . PHP_EOL;
var_dump($result);
// use fetchAll() with constants
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$result = $q->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
echo 'Result 1' . PHP_EOL;
var_dump($result);
// use setFetchMode with constants
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$q->setFetchMode(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
$result = $q->fetchAll();
echo 'Result 2' . PHP_EOL;
var_dump($result);

测试数据

mysql> select * from test.service_table;
+----+------+
| id | name |
+----+------+
|  1 | one  |
|  2 | two  |
+----+------+

结果 0

这是默认值,结果不分组,并且同时存在基于名称的字段和基于索引的字段:

array(2) {
  [0] =>
  array(4) {
    'id' => string(1) "1"
    [0] => string(1) "1"
    'name' => string(3) "one"
    [1] => string(3) "one"
  }
  [1] =>
  array(4) {
    'id' => string(1) "2"
    [0] => string(1) "2"
    'name' => string(3) "two"
    [1] => string(3) "two"
  }
}

结果 1

这是$q->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC)的结果。我们有FETCH_GROUPFETCH_ASSOC的影响:

array(2) {
  [1] => array(1) {
    [0] => array(1) {
      'name' => string(3) "one"
    }
  }
  [2] => array(1) {
    [0] => array(1) {
      'name' => string(3) "two"
    }
  }
}

结果 2

这是$q->setFetchMode(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);的结果,我们只有FETCH_ASSOC的效果:

array(2) {
  [0] => array(2) {
    'id' => string(1) "1"
    'name' => string(3) "one"
  }
  [1] => array(2) {
    'id' => string(1) "2"
    'name' => string(3) "two"
  }
}

这样,FETCH_GROUP适用于fetchAll(),但不适用于setFetchMode()FETCH_ASSOC这两种情况下都有效。

PHP 文档

现在,来自文档的间接确认:

以下是所有 PDO 常量的列表。PDO::FETCH_FUNC的描述说:

允许完全自定义动态处理数据的方式(仅在PDOStatement::fetchAll()内部有效(。

所以我们知道至少这个常数只适用于fetchAll(),并且可以假设其他常量可能不是在所有地方都有效。

另外,如果我们查看 fetch()的文档 ,我们在那里看到有限的常量列表。

例如,PDO::FETCH_GROUPPDO::FETCH_UNIQUE存在于fetchAll()描述中,但不存在于fetch()描述中。

所以我认为与多行运算相关的常量,例如 PDO::FETCH_GROUP ,仅用于fetchAll(),被fetch()setFetchMode()忽略。


如何获取按 ID 编制索引的数组

我尝试了几种组合,看起来 FETCH_GROUP + FETCH_UNIQUE做到了。

法典

$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$result = $q->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_UNIQUE | PDO::FETCH_ASSOC);
var_dump($result);

结果

array(2) {
  [1] => array(1) {
    'name' => string(3) "one"
  }
  [2] => array(1) {
    'name' => string(3) "two"
  }
}

另一种选择是将FETCH_FUNC与自定义函数一起使用来格式化数据,请参阅fetchAll()文档。