8

我想知道我是否做得很好或 fetchAll() 不适用于 WHILE。

这是一个例子

$db=new PDO("mysql:host=" .$dbhost. "; dbname=" . $dbname, $dbuser, $dbpass);

$page=$db->prepare("SELECT * FROM page");
$page->execute();

foreach ($page->fetchAll(PDO::FETCH_ASSOC) as $row) {

//echo a row
//is working
}

但是,我如果尝试循环一段时间

while ($row=$page->fetchAll(PDO::FETCH_ASSOC)){

//echo a row
//Show empty
}

我尝试只使用 fetch(),它正在工作,我的问题是:为什么 fetchAll() 不适用于“WHILE”?

4

5 回答 5

21

Fetch all 返回结果集中剩余的所有记录。考虑到这一点,您的 foreach 能够按预期迭代结果集。

对于等效的 while 实现应该使用$page->fetch(PDO::FETCH_ASSOC);

while ($row = $page->fetch(PDO::FETCH_ASSOC)){
   // do something awesome with row
} 

如果您想使用一段时间并获取所有您可以做的

$rows = $page->fetchAll(PDO::FETCH_ASSOC);

// use array_shift to free up the memory associated with the record as we deal with it
while($row = array_shift($rows)){
   // do something awesome with row
}

不过要警告一句:fetch all 会做到这一点,如果结果大小很大,它将给您机器上的资源带来压力。如果我知道结果集会很小,或者我通过对查询应用限制来强制这样做,我只会这样做。

于 2013-07-18T16:46:04.217 回答
8

来自 PHP 手册:

while 语句的含义很简单。它告诉 PHP 重复执行嵌套语句,只要 while 表达式的计算结果为 TRUE。

由于您使用的方法返回一个数组, while ($row=$page->fetchAll(PDO::FETCH_ASSOC))因此将 $row 设置为整个结果集的数组。您所期望的是 fetchAll 方法扩展Iterator 类,但事实并非如此。

Aforeach是去这里的正确方法。

于 2013-07-18T16:48:12.830 回答
6

无需遍历记录集,因为fetchAll- 好吧 -在一个命令中获取所有记录。不错,不是吗?

$rows = $page->fetchAll(PDO::FETCH_ASSOC);

// $rows is an array containing all records...
foreach ($rows as $row)
    echo $row->fieldname;
于 2013-07-18T16:52:43.237 回答
2

我试图重现你的情况。看这里:

脚本.php

<?php
$host = 'localhost';
$user = "user";
$password = '';
$db_name = 'test';
$port = 3306;

try
{
    $connection = new PDO("mysql:host=$host;port=$port;dbname=$db_name", $user, $password);
    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
    echo 'Connection failed: ' . $e->getMessage();
}

$page=$connection->prepare("SELECT * FROM Document");
$page->execute();

while ($row = $page->fetchAll(PDO::FETCH_ASSOC)) {
    var_dump($row);
}

数据库测试

DROP TABLE IF EXISTS `Document`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Document` (
  `DataID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Description` varchar(50) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`DataID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `Document`
--

LOCK TABLES `Document` WRITE;
/*!40000 ALTER TABLE `Document` DISABLE KEYS */;
INSERT INTO `Document` VALUES (1,'!!!'),(2,'This is document 2'),(3,'This is document 3'),(4,'This is document 4'),(5,'Hello');
/*!40000 ALTER TABLE `Document` ENABLE KEYS */;
UNLOCK TABLES;

输出

$php script.php
array(5) {
  [0]=>
  array(2) {
    ["DataID"]=>
    string(1) "1"
    ["Description"]=>
    string(3) "!!!"
  }
  [1]=>
  array(2) {
    ["DataID"]=>
    string(1) "2"
    ["Description"]=>
    string(18) "This is document 2"
  }
  [2]=>
  array(2) {
    ["DataID"]=>
    string(1) "3"
    ["Description"]=>
    string(18) "This is document 3"
  }
  [3]=>
  array(2) {
    ["DataID"]=>
    string(1) "4"
    ["Description"]=>
    string(18) "This is document 4"
  }
  [4]=>
  array(2) {
    ["DataID"]=>
    string(1) "5"
    ["Description"]=>
    string(5) "Hello"
  }
}

输出意味着,while 语句执行一次并打印所有行,查询应该返回,这是绝对正确的,因为 fetchAll 返回包含所有行的数组数组。PHP 将其解释为 true 并且 while 运行一次。

Whileforeach将遍历数组数组,每次都会有相应的行。

于 2013-07-18T16:58:09.313 回答
0

使用fetchAllIn while 循环,您已经在第一次迭代中获取了所有记录,并且下次没有任何内容可以获取。foreach您还获取了第一行中的所有记录,但使用foreach结果进行迭代。

于 2013-07-18T16:46:37.160 回答