以下代码:
<?php
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
echo "Connection is successful!<br/>";
$sql = "SELECT * FROM users";
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
$dbh = null;
}
catch (PDOexception $e) {
echo "Error is: " . $e-> etmessage();
}
输出:
Connection is successful!
person A-male
person B-female
两次运行“foreach”不是我的目的,我只是好奇为什么两个“foreach”语句只输出一次结果?
以下是类似案例:
<?php
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
echo "Connection is successful!<br/>";
$sql = "SELECT * FROM users";
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
echo "<br/>";
$result = $users->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
$dbh = null;
}
catch (PDOexception $e) {
echo "Error is: " . $e-> etmessage();
}
输出:
Connection is successful!
person A-male
person B-female
SCREAM: Error suppression ignored for
Warning: Invalid argument supplied for foreach()
但是当我从上面的代码中删除第一个“foreach”时,输出将变为正常:
<?php
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
echo "Connection is successful!<br/>";
$sql = "SELECT * FROM users";
$users = $dbh->query($sql);
echo "<br/>";
$result = $users->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
$dbh = null;
}
catch (PDOexception $e) {
echo "Error is: " . $e-> etmessage();
}
输出:
Connection is successful!
user_id-0000000001
name-person A
sex-male
任何人都知道为什么会这样?我只是一个PHP初学者,谢谢你的帮助!
答案 0 :(得分:20)
PDOStatement
(你在$users
中)是一个前向光标。这意味着,一旦消耗(第一个foreach
迭代),它将不会回退到结果集的开头。
您可以在foreach
之后关闭光标并再次执行该语句:
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
$users->execute();
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
或者您可以使用带有fullcache的定制CachingIterator
进行缓存:
$users = $dbh->query($sql);
$usersCached = new CachedPDOStatement($users);
foreach ($usersCached as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
foreach ($usersCached as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
你find the CachedPDOStatement
class as a gist。缓存迭代器可能比将结果集存储到数组更加理智,因为它仍然提供它所包装的PDOStatement
对象的所有属性和方法。
答案 1 :(得分:11)
foreach over a statement只是常规单向fetch()循环的语法糖。如果您想多次循环数据,请先将其选为常规数组
$sql = "SELECT * FROM users";
$stm = $dbh->query($sql);
// here you go:
$users = $stm->fetchAll();
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
echo "<br/>";
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
也退出try..catch
件事。不要使用它,但为PHP和PDO设置正确的错误报告
答案 2 :(得分:8)
这是因为您正在读取游标而不是数组。这意味着您正在按顺序读取结果,当您到达结束时,您需要将光标重置为结果的开头以再次读取它们。
如果您确实希望多次读取结果,可以使用fetchAll(http://www.php.net/manual/en/pdostatement.fetchall.php)将结果读入真实数组,然后按预期工作。
答案 3 :(得分:0)
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
此处$users
是一个PDOStatement
对象,您可以在其上进行迭代。第一次迭代输出所有结果,第二次迭代不执行任何操作,因为您只能迭代结果一次。那是因为从数据库流式传输数据并使用foreach
迭代结果本质上是简写:
while ($row = $users->fetch()) ...
完成该循环后,您需要重置数据库端的光标,然后才能再次循环。
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
echo "<br/>";
$result = $users->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
这里所有结果都是由第一个循环输出的。对fetch
的调用将返回false
,因为您已经用完了结果集(见上文),因此在尝试循环false
时出错。
在最后一个示例中,您只是获取第一个结果行并在其上循环。