带有 foreach 和 fetch 的 PHP PDO
Posted
技术标签:
【中文标题】带有 foreach 和 fetch 的 PHP PDO【英文标题】:PHP PDO with foreach and fetch 【发布时间】:2013-03-01 10:13:49 【问题描述】:以下代码:
<?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
为什么会这样?
【问题讨论】:
【参考方案1】:再次执行相同的查询只是为了得到你已经得到的结果,正如接受的答案中所建议的那样,是一种疯狂。
foreach 语句只是常规单向 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 设置proper error reporting
【讨论】:
感谢您的提示,学习准备和执行是我的下一步。 @YourCommonSense 为什么你的答案中每个循环都有两个?我不是找错,只是学习…… 使用 pdo->query() 绝对不是使用库的错误方式。 exec() 和 query() 可以使用。唯一错误的用法是尝试通过该语句两次,他应该只有 fetchAll() 然后他可以通过数组迭代几次。如果您坚持使用 query() 是错误的,请给出适当的请说明原因。 我也不清楚使用query()
有什么问题,如mentioned in your tutorial。这个特定的实现有什么不理想的地方吗?
@showdev 你是对的。我不记得这个答案的上下文,但肯定看起来很陌生,所以我编辑了它【参考方案2】:
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/>";
或者您可以使用定制的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
对象的所有属性和方法。
【讨论】:
谢谢,虽然看不清楚,但是你的例子对我以后肯定有用。 请查看另一个编辑,我有一个错字:在第一个foreach
之后使用 $users->execute();
将光标重置到结果集的开头。这很可能是您正在寻找的。缓存是一个更具体的解决方案,并不是真正必要的,你可以这样做$users->execute();
。我添加它只是为了一般示例。
谢谢,第一个好像比较清楚,我去看看php手册中的execute函数。
是的,它更直接。方法在这里:php.net/manual/en/pdostatement.execute.php【参考方案3】:
这是因为您正在读取游标,而不是数组。这意味着您正在按顺序阅读结果,当您读到结尾时,您需要将光标重置到结果的开头以再次阅读它们。
如果您确实想多次读取结果,可以使用fetchAll 将结果读入一个真正的数组,然后它会按您的预期工作。
【讨论】:
【参考方案4】:$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
时会出错。
在最后一个示例中,您只是获取第一个结果行并对其进行循环。
【讨论】:
以上是关于带有 foreach 和 fetch 的 PHP PDO的主要内容,如果未能解决你的问题,请参考以下文章
带有 PDO::FETCH_ASSOC 的 foreach 循环,提供的参数无效
PHP PDO fetch 和 foreach - 我没有得到第一列
使用 PHP 和 codeigniter 显示带有 foreach 函数的固定表
在本地主机上运行的 Vue 应用程序中使用带有 php 文件的 JavaScript fetch() - 相对 URL 问题