如何绑定SQL插入的数组?[复制]

How to bind array for SQL insert? [duplicate]

提问人: 提问时间:8/3/2023 最后编辑:Dharman 更新时间:8/3/2023 访问量:47

问:

尝试绑定数组(第一个数组绑定)以防止 SQL 注入

这是工作代码:

if (isset($_POST['checkbox_selected']))
{       
    $valuesArr = array(); 
    foreach ($_POST['checkbox_selected'] as $key => $value) {
        //Retrieve Array ID to find Row number for CSVOption Column
        $findrow = array_search_partial($attributeid, $value);
        //attribure value is assigned to attribute id on form submit 
        $attribute = $value;            
        $csv = $csvcolumn[$findrow];        
        $valuesArr[] = "('$userid', '$feed_id', '$attribute', '$csv')";         
    }
        
    $sql = "INSERT INTO map (user_id, feed_id, attribute_id, csvcolumn) values ";
    $sql .= implode(',', $valuesArr);
    mysqli_query($conn,$sql);
}

我无法绑定数组,尝试:

$sql = "INSERT INTO map (user_id, feed_id, attribute_id, csvcolumn) VALUES (?, ?, ? ,?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('iiii', implode(',', $valuesArr));
$stmt->execute();

echo implode(',', $valuesArr)
//('1', '1', '13', '9') //This is the the array which gets inserted into the SQL
//(user_id, feed_id, attribute_id, csvcolumn) //where these are the values assigned in the 1st statement 
PHP MySQLI

评论

0赞 KompjoeFriek 8/3/2023
我认为你可以用参数解包来做到这一点:php.net/manual/en/...。尝试:将 的值传入$stmt->bind_param('iiii', ...$valuesArr);$valuesArrbind_param
2赞 Markus Zeller 8/3/2023
为什么这么复杂?保留绑定并传递以直接执行。.$stmt->execute([$userid, $feed_id, $attribute, $csv]);

答:

0赞 bguebert 8/3/2023 #1

而不是

$stmt->bind_param('iiii', implode(',', $valuesArr));

你可以使用

$stmt->bind_param('iiii', $userid, $feed_id, $attribute, $csv);

这条线

$valuesArr[] = "('$userid', '$feed_id', '$attribute', '$csv')";  

创建一个包含一个字符串的数组,所有字段都连接在一起,我不确定你是故意这样做的。内爆返回数组的第一个也是唯一一个成员。

3赞 Sammitch 8/3/2023 #2

您有两个问题:

  1. 您没有使用正确的绑定语法。
  2. 您正在尝试在单个预准备语句中插入多行。
if (isset($_POST['checkbox_selected']))
{
    $sql = "INSERT INTO map (user_id, feed_id, attribute_id, csvcolumn) VALUES (?, ?, ?, ?);";
    // prepare only has to happen once
    $stmt = $conn->prepare($sql);

    $conn->begin_transaction();
    try {
        foreach ($_POST['checkbox_selected'] as $key => $value) {
            $findrow = array_search_partial($attributeid, $value);
            $attribute = $value;            
            $csv = $csvcolumn[$findrow];
            
            $stmt->bind_param('iiii', $userid, $feed_id, $attribute, $csv);
            $stmt->execute();
        }
        $conn->commit();
    } catch(mysqli_sql_exception $e) {
        $conn->rollback(); // immediately roll back changes
        throw $e; // re-throw exception
    }
}

尝试将多个查询打包到单个查询中唯一很少的好处是,它被包装到包装查询的隐式事务中。这种方法的其他一切都是不利的。显式打开包装绑定/执行循环的事务可以获得相同的好处 [错误回滚、IO 批处理],同时还可以利用预准备语句的好处。[单个简单查询解析、参数化等]VALUES (), ...

评论

0赞 8/3/2023
谢谢,这非常有效,对于我这个对 PHP 比较陌生的人来说,这绝对更容易理解。一些我以前没有遇到过的新方法,随着我的进步,我将不得不研究更多($conn->begin_transaction(), $conn->commit(); $conn->rollback();
0赞 Sammitch 8/4/2023
本文对什么是数据库事务进行了很好的概述。默认情况下,大多数数据库 API 会隐式地将每个查询包装在自己的事务中,但手动启动一个查询以涵盖由多个语句组成的操作很有用。