带有foreach和fetch的PHP PDO

nut*_*nut 16 php mysql foreach pdo 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) {
        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();
}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

Connection is successful!

person A-male
person B-female
Run Code Online (Sandbox Code Playgroud)

两次运行"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();
}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

Connection is successful!

person A-male
person B-female

SCREAM: Error suppression ignored for
Warning: Invalid argument supplied for foreach()
Run Code Online (Sandbox Code Playgroud)

但是当我从上面的代码中删除第一个"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();
}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

Connection is successful!

user_id-0000000001
name-person A
sex-male
Run Code Online (Sandbox Code Playgroud)

任何人都知道为什么会这样?我只是一个PHP初学者,谢谢你的帮助!

hak*_*kre 22

A 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/>";
}
Run Code Online (Sandbox Code Playgroud)

或者你可以使用CachingIteratorfullcache 定制缓存:

$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/>";
}
Run Code Online (Sandbox Code Playgroud)

发现这个CachedPDOStatement课程是一个要点.缓存迭代器可能比将结果集存储到数组更加理智,因为它仍然提供PDOStatement它所包装的对象的所有属性和方法.


You*_*nse 12

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/>";
}
Run Code Online (Sandbox Code Playgroud)

也放弃那try..catch件事.不要使用它,但为PHP和PDO设置正确的错误报告

  • @YourCommonSense为什么答案中的每个循环都有两个?我没有找错,只是在学习...... (4认同)
  • 使用pdo-> query()绝对不是使用库的错误方法.exec()和query()是有用的.唯一错误的用法是试图通过语句两次,他应该只有fetchAll()然后他可以通过数组迭代几次..如果你坚持你的话,使用query()是错误的,给一个合适的请原因. (3认同)

小智 8

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

如果您确实希望多次读取结果,可以使用fetchAll(http://www.php.net/manual/en/pdostatement.fetchall.php)将结果读入真正的数组,然后它就可以工作了正如你所料.