如何使用 implode() 在 PHP 中使用准备好的语句将多个整数插入到 IN 语句中?
How do I use implode() to insert multiple integers into IN statement using prepared statements in PHP?
上下文
我有一个供稿系统,用户可以在其中关注我网站上的其他用户并查看他们的 posted 内容,例如他们创建的话题。为此,我使用 AJAX 发送一个数组,其中包含用户关注的人员的所有用户 ID,以便在 SQL 语句中查询(我的 DBMS 是 MySQL)。在 PHP 中,然后我尝试获取此数组并使用 IN
语句将其放入我的 SQL 查询中。在这种特定情况下,用户关注另外两个 ID 为 11 和 12 的人。因此在通过 AJAX 将此数据发送到 PHP 代码后,我可以使用 print_r($_POST['following'])
并获得此结果:
Array ( [0] => 11 [1] => 12 )
要在我的 SQL 查询中使用它,我使用以下代码:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$q = "SELECT forums.forum_id, forums.forum_title, forums.message,
forums.idUsers, forums.box_id, forums.date,
forums.seen, users.uidUsers, profileimages.image
FROM forums
JOIN users
JOIN profileimages
ON forums.idUsers = users.idUsers
AND profileimages.idUsers = users.idUsers
WHERE forums.idUsers
IN (?) //code in question
ORDER BY forums.forum_id DESC
LIMIT 5
OFFSET ?";
$stmt = mysqli_prepare($conn, $q);
mysqli_stmt_bind_param($stmt, 'ii', $followingArray, $offset);
$following = $_POST['following'];
$followingArray = implode(", ", $following); //code in question
$offset = $_POST['offset'];
mysqli_stmt_execute($stmt);
执行查询后,我获取信息并将其发送回服务器。当我这样做时,有五个返回行:
[{idUsers: 11, forumId: 11, seen: "false", forumTitle: "sixth random thread",…},…]
0: {idUsers: 11, forumId: 11, seen: "false", forumTitle: "sixth random thread",…}
1: {idUsers: 11, forumId: 10, seen: "false", forumTitle: "fifth random thread",…}
2: {idUsers: 11, forumId: 9, seen: "false", forumTitle: "fourth random thread",…}
3: {idUsers: 11, forumId: 8, seen: "false", forumTitle: "third random thread",…}
4: {idUsers: 11, forumId: 7, seen: "false", forumTitle: "second random thread",…}
这很好,除了这只考虑涉及用户 ID 11 的 posts,而不是 11 和 12。如果 IN
语句包含 posts 的用户 ID 为 12,则结果会有所不同。直接进入数据库手动输入值后再次查询后,像这样:
SELECT forums.forum_id, forums.forum_title, forums.message,
forums.idUsers, forums.box_id, forums.date,
forums.seen, users.uidUsers, profileimages.image
FROM forums
JOIN users
JOIN profileimages
ON forums.idUsers = users.idUsers
AND profileimages.idUsers = users.idUsers
WHERE forums.idUsers IN ('11', '12')
ORDER BY forums.forum_id DESC
LIMIT 5 OFFSET 0
您发现结果行不同;第一个结果是来自用户 ID 为 12 的用户 post。
[,…]
[{idUsers: "12", forumId: "12", seen: "false", forumTitle: "first new content here",…},…]
0: {idUsers: "12", forumId: "12", seen: "false", forumTitle: "first new content here",…}
1: {idUsers: "11", forumId: "11", seen: "false", forumTitle: "sixth random thread",…}
2: {idUsers: "11", forumId: "10", seen: "false", forumTitle: "fifth random thread",…}
3: {idUsers: "11", forumId: "9", seen: "false", forumTitle: "fourth random thread",…}
4: {idUsers: "11", forumId: "8", seen: "false", forumTitle: "third random thread",…}
这让我相信我的 implode()
准备语句的实现是不正确的。
问题
我是否应该使用 implode()
函数更改某些内容,例如在数组中的每个值周围加上引号,以使其与 MySQL 中的 IN
语句一起使用?
我尝试过的事情
认为我的 implode()
函数格式不正确,我尝试将 $followingArray
变量从 $followingArray = implode("', '", $following);
更改为 $followingArray = "'" . implode("', '", $following) . "'";
,结果只返回 0 行。尝试将多个值插入 SQL 语句时,如何格式化我的 implode()
函数才能正常工作?
根据这个问题的回答试试这个
$followingArray = "'" . implode("','", $following) . "'";
你永远不应该自己弄乱引号,因为它会导致 sql 注入的风险。
此外,在这个特定的例子中,你插入的是数字,但如果你想插入像“O'Connor”这样的字符串,它在一般情况下是行不通的,甚至不谈论你是否想存储包含 '
和 "
的任意文本:准备好的语句会处理所有问题,安全性和引用意大利面条。
我的建议是首先 count
您将要查询的 ID 数量,然后在您的 IN
子句中添加那么多 ?
像这样
$idCount = //count ids
$questmarks = array_fill(0, $idCount, "?");
$sql .= "IN(".implode(",", $questmarks).")";
如果您要查询 5 个 ID,则准备好的 SQL 字符串将如下所示:
SELECT ...
WHERE
AND id IN (?,?,?,?,?)
LIMIT ?
然后按顺序绑定所有参数。
$params = [$id1,$id2,$id3,$id4,$id5,$offset];
mysqli_stmt_bind_param($stmt, "ii", ...$params);
上下文
我有一个供稿系统,用户可以在其中关注我网站上的其他用户并查看他们的 posted 内容,例如他们创建的话题。为此,我使用 AJAX 发送一个数组,其中包含用户关注的人员的所有用户 ID,以便在 SQL 语句中查询(我的 DBMS 是 MySQL)。在 PHP 中,然后我尝试获取此数组并使用 IN
语句将其放入我的 SQL 查询中。在这种特定情况下,用户关注另外两个 ID 为 11 和 12 的人。因此在通过 AJAX 将此数据发送到 PHP 代码后,我可以使用 print_r($_POST['following'])
并获得此结果:
Array ( [0] => 11 [1] => 12 )
要在我的 SQL 查询中使用它,我使用以下代码:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$q = "SELECT forums.forum_id, forums.forum_title, forums.message,
forums.idUsers, forums.box_id, forums.date,
forums.seen, users.uidUsers, profileimages.image
FROM forums
JOIN users
JOIN profileimages
ON forums.idUsers = users.idUsers
AND profileimages.idUsers = users.idUsers
WHERE forums.idUsers
IN (?) //code in question
ORDER BY forums.forum_id DESC
LIMIT 5
OFFSET ?";
$stmt = mysqli_prepare($conn, $q);
mysqli_stmt_bind_param($stmt, 'ii', $followingArray, $offset);
$following = $_POST['following'];
$followingArray = implode(", ", $following); //code in question
$offset = $_POST['offset'];
mysqli_stmt_execute($stmt);
执行查询后,我获取信息并将其发送回服务器。当我这样做时,有五个返回行:
[{idUsers: 11, forumId: 11, seen: "false", forumTitle: "sixth random thread",…},…]
0: {idUsers: 11, forumId: 11, seen: "false", forumTitle: "sixth random thread",…}
1: {idUsers: 11, forumId: 10, seen: "false", forumTitle: "fifth random thread",…}
2: {idUsers: 11, forumId: 9, seen: "false", forumTitle: "fourth random thread",…}
3: {idUsers: 11, forumId: 8, seen: "false", forumTitle: "third random thread",…}
4: {idUsers: 11, forumId: 7, seen: "false", forumTitle: "second random thread",…}
这很好,除了这只考虑涉及用户 ID 11 的 posts,而不是 11 和 12。如果 IN
语句包含 posts 的用户 ID 为 12,则结果会有所不同。直接进入数据库手动输入值后再次查询后,像这样:
SELECT forums.forum_id, forums.forum_title, forums.message,
forums.idUsers, forums.box_id, forums.date,
forums.seen, users.uidUsers, profileimages.image
FROM forums
JOIN users
JOIN profileimages
ON forums.idUsers = users.idUsers
AND profileimages.idUsers = users.idUsers
WHERE forums.idUsers IN ('11', '12')
ORDER BY forums.forum_id DESC
LIMIT 5 OFFSET 0
您发现结果行不同;第一个结果是来自用户 ID 为 12 的用户 post。
[,…]
[{idUsers: "12", forumId: "12", seen: "false", forumTitle: "first new content here",…},…]
0: {idUsers: "12", forumId: "12", seen: "false", forumTitle: "first new content here",…}
1: {idUsers: "11", forumId: "11", seen: "false", forumTitle: "sixth random thread",…}
2: {idUsers: "11", forumId: "10", seen: "false", forumTitle: "fifth random thread",…}
3: {idUsers: "11", forumId: "9", seen: "false", forumTitle: "fourth random thread",…}
4: {idUsers: "11", forumId: "8", seen: "false", forumTitle: "third random thread",…}
这让我相信我的 implode()
准备语句的实现是不正确的。
问题
我是否应该使用 implode()
函数更改某些内容,例如在数组中的每个值周围加上引号,以使其与 MySQL 中的 IN
语句一起使用?
我尝试过的事情
认为我的 implode()
函数格式不正确,我尝试将 $followingArray
变量从 $followingArray = implode("', '", $following);
更改为 $followingArray = "'" . implode("', '", $following) . "'";
,结果只返回 0 行。尝试将多个值插入 SQL 语句时,如何格式化我的 implode()
函数才能正常工作?
根据这个问题的回答试试这个
$followingArray = "'" . implode("','", $following) . "'";
你永远不应该自己弄乱引号,因为它会导致 sql 注入的风险。
此外,在这个特定的例子中,你插入的是数字,但如果你想插入像“O'Connor”这样的字符串,它在一般情况下是行不通的,甚至不谈论你是否想存储包含 '
和 "
的任意文本:准备好的语句会处理所有问题,安全性和引用意大利面条。
我的建议是首先 count
您将要查询的 ID 数量,然后在您的 IN
子句中添加那么多 ?
像这样
$idCount = //count ids
$questmarks = array_fill(0, $idCount, "?");
$sql .= "IN(".implode(",", $questmarks).")";
如果您要查询 5 个 ID,则准备好的 SQL 字符串将如下所示:
SELECT ...
WHERE
AND id IN (?,?,?,?,?)
LIMIT ?
然后按顺序绑定所有参数。
$params = [$id1,$id2,$id3,$id4,$id5,$offset];
mysqli_stmt_bind_param($stmt, "ii", ...$params);