循环中的预准备语句

prepared statement in the loop

提问人:luca amarelli 提问时间:12/22/2021 最后编辑:Dharmanluca amarelli 更新时间:12/22/2021 访问量:60

问:

我有一个问题,我太久都想不通了。基本上我有带有用户名的表格(表中有 1 个唯一的用户名)和 1 个相应的图像文件。有些用户有图像文件,有些则没有。用户名存储在数组 $Users[] 中。我正在尝试使用以下方法获取每个用户的图像文件名:

$stmt = $db->prepare("SELECT file_name FROM images WHERE BINARY username=?"); 
    for($temp1=0; $temp1<count($Users); $temp1++){
        $stmt->bind_param("s", $Users[$temp1]);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($ImgFileName);
        $stmt->fetch();
        $imageURL[$temp1]=$ImgFileName;
    }

但是,这有令人讨厌的行为。比如说,当代码循环时,如果用户 User[0] 有与之相关的$ImgFileName,但 User[1]、User[2] 等没有,那么$ImgFileName将用于具有可用图像的最后一个用户,而不是 null。这种情况会发生,直到循环中的某个用户再次在表中具有图像文件名。因此,如果我在循环后打印$imageURL[]数组,它看起来像:

$Users[]=[user1,user2,user3,user4,user5]
$imageURL[]=[img001.png,img001.png,img001.png,img231.png,img124.png,img124.png]

而不是

$Users[]=[user1,user2,user3,user4,user5]
$imageURL[]=[img001.png,,,img231.png,img124.png,]

有人知道为什么吗?

PHP 数组 循环 mysqli

评论

0赞 Dharman 12/22/2021
我很确定使用 PDO 会容易 10 倍。你为什么用mysqli这样做吗?
0赞 luca amarelli 12/22/2021
我实际上只是通过做一些项目来学习 PHP、JavaScript,并没有真正使用 PDO。但会看一看。谢谢
0赞 Dharman 12/22/2021
如果你刚刚开始学习 PHP,那么你应该学习 PDO 而不是 mysqli。PDO更容易,更适合初学者。从这里开始 phpdelusions.net/pdo & websitebeaver.com/...
0赞 luca amarelli 12/22/2021
谢谢。从sql注入的角度来看,一种方式比另一种方式更好吗?或者也许是任何其他安全功能?
0赞 Dharman 12/22/2021
不,在安全方面,它们是相同的。两者都提供准备好的语句,PDO 具有更多功能,这使得编码变得更加容易。

答:

1赞 Dharman 12/22/2021 #1

原因是因为您从未在循环中重置。$ImgFileName

放入循环内。$ImgFileName = null;

您也可以取消设置变量,这将导致相同的结果。

for($temp1=0; $temp1<count($Users); $temp1++){
    $stmt->bind_param("s", $Users[$temp1]);
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($ImgFileName);
    $stmt->fetch();
    $imageURL[$temp1]=$ImgFileName;

    unset($ImgFileName);
}

评论

0赞 luca amarelli 12/22/2021
嗯,奇怪,我试过了,确实有效。我预计每当 SQL 语句给出 null 时,如果我只为一个没有文件名的用户运行它,它就会这样做,那么它会自动绑定 $ImgFileName = null;。很高兴我问了,因为我没想到会这样。非常感谢,先生。
0赞 Dharman 12/22/2021
@lucaamarelli 当准备好的语句找不到任何行时,它不会返回任何值,甚至不会返回 null。
0赞 luca amarelli 12/22/2021
是的,现在我明白了。吸取的教训。再次感谢你。
1赞 Nigel Ren 12/22/2021 #2

另一种方法是将文件名存储在以名称为索引的数组中(同时确保每次都清空图像名称)......

for($temp1=0; $temp1<count($Users); $temp1++){
    $ImgFileName = '';
    $userName = $Users[$temp1];
    $stmt->bind_param("s", $userName);
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($ImgFileName);
    $stmt->fetch();
    $imageURL[$userName] = $ImgFileName;
}

如果您还将此与 using 结合使用(从 How do you use IN clauses with mysqli prepared statements),您可以在一次执行中获取已知用户和文件名的列表......in

$stmt = $db->prepare("SELECT username, file_name
                       FROM images 
                       WHERE username in...

只需遍历结果并将它们添加到数组中即可。