PDOStatement:在 `fetchAll($mode);` 和 `setFetchMode($mode); 之间得到不同的结果;获取所有();`

Posted

技术标签:

【中文标题】PDOStatement:在 `fetchAll($mode);` 和 `setFetchMode($mode); 之间得到不同的结果;获取所有();`【英文标题】:PDOStatement: Getting different results between `fetchAll($mode);` and `setFetchMode($mode); fetchAll();` 【发布时间】:2014-01-04 10:22:06 【问题描述】:

我有一个关于 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);

【问题讨论】:

哦,好吧,我认为这无关紧要,因为我只是在问两者之间是否有区别,如果有,那是什么...但是如果我添加它可能会更好 应该有区别 所以我添加了一个返回的示例,有什么区别,因为在我看来代码应该返回相同的...... 【参考方案1】:

解释似乎是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-&gt;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-&gt;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 constants 的列表。 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() 文档。

【讨论】:

我认为你最好在这里删除你的例子,我们已经有一个例子在问题中,所以最好只解释原因,而不是一个新的例子。 @TaReQMahMooD 这个问题只涉及到 fetchall 和 setFetchMode 的区别。我的解释是基于将它们与问题中不存在的默认行为(不是标志)进行比较。如果我删除示例,恐怕要遵循逻辑会很复杂。 谢谢,这是一个很好的解释,示例只是支持它,享受赏金:) @Arth 谢谢,我还能够从 php 来源确认我的假设,setFetchMode 只是忽略了 FETCH_GROUP。我更新了答案。

以上是关于PDOStatement:在 `fetchAll($mode);` 和 `setFetchMode($mode); 之间得到不同的结果;获取所有();`的主要内容,如果未能解决你的问题,请参考以下文章

88)PHP,PDOStatement对象

PHP PDO 如何在内部工作?

Web 应用程序中的数据库游标获取

如何在 PDOStatement::bindValue() 中定义变量类型?

警告:PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: parame

PHP使用PDOStatement处理结果集