带有foreach和fetch的PHP-PDO

带有foreach和fetch的PHP-PDO,php,mysql,pdo,foreach,fetch,Php,Mysql,Pdo,Foreach,Fetch,以下代码: <?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) {

以下代码:

<?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();
}
运行两次“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();
}
但当我从上述代码中删除第一个“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();
}

为什么会发生这种情况?

这是因为您正在读取的是光标,而不是数组。这意味着您正在按顺序读取结果,当您到达结果的末尾时,需要将光标重置到结果的开头以再次读取结果

如果您确实希望多次读取结果,可以使用将结果读取到真实数组中,然后它将按照您的预期工作

$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 = $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/>";
}
$users=$dbh->query($sql);
foreach($users作为$row){
打印$row[“name”]。“-”$row[“sex”]。“
”; } 回声“
”; $result=$users->fetch(PDO::fetch_ASSOC); foreach($结果为$key=>$value){ 回声$key.“-”$value.“
”; }
这里所有的结果都由第一个循环输出。调用
fetch
将返回
false
,因为您已经耗尽了结果集(请参见上文),因此尝试循环
false
时会出现错误


在上一个示例中,您只需获取第一个结果行并在其上循环。

一个
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/>";
}

你。缓存itertor可能比将resultset存储到数组中更明智,因为它仍然提供它所包装的
PDOStatement
对象的所有属性和方法。

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/>";
}
$sql=“选择*来自用户”;
$stm=$dbh->query($sql);
//给你:
$users=$stm->fetchAll();
foreach($users作为$row){
打印$row[“name”]。“-”$row[“sex”]。“
”; } 回声“
”; foreach($users作为$row){ 打印$row[“name”]。“-”$row[“sex”]。“
”; }

同时退出
try..catch
这件事。不要使用它,但要为PHP和PDO设置参数

谢谢你的提示,学习准备和执行是我的下一步。@YourCommonSense为什么你的答案中每个循环有两个?我不是吹毛求疵,只是在学习…使用pdo->query()绝对不是使用库的错误方式。exec()和query()将在其中使用。唯一错误的用法是尝试遍历语句两次,他应该只使用fetchAll(),然后可以在数组中迭代几次。。如果你坚持使用query()是错误的,请给出一个适当的理由。我也不清楚使用
query()
有什么错。这个特定的实现有什么不理想的地方吗?@showdev你说得对。我不记得这个答案的上下文,但它看起来确实很陌生,所以我编辑了它,虽然我不能清楚地理解它,但你的例子对我将来肯定有用。请看另一个编辑,我有一个错误:使用
$users->execute()foreach
之后进行code>以将光标重置到结果集的开头。这很可能就是你要找的。缓存是一种更为具体的解决方案,并不像您所做的那样真正必要。我添加它只是为了一般的例子。谢谢,第一个对我来说似乎更清楚,我将研究php手册中的执行函数。是的,它更直接。方法如下:
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/>";
}
$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/>";
}
$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/>";
}
$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/>";
}