使用具有大量INSERT值的PDO的正确方法

时间:2015-06-11 13:51:21

标签: php mysql post pdo

我正在使用PDO在具有10个输入字段的表单上插入来自用户的MySQL DB输入。我通过这样做来创建一个包含$_POST值的数值数组:

foreach ($_POST as $key => $val)
{
     //testInput() sanitizes the input
     $postArray[] = testInput($val);
}

通过在线浏览的所有示例和答案以及使用PDO插入数据的SO,他们做了类似的事情(https://stackoverflow.com/a/767520/3040381):

$db = new PDO("...");
$statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
$statement->execute(array(':some_id' => $row['id']));

我遇到的问题是,我有近10个用户输入要插入到我的数据库中。使用上面的方法,我必须做这样的事情:

$statement->execute(array(':id1' => $row['id'], ':id2' => $row['id2'], ':id3' => $row['id3'], ........':id10' => $row['id10'], ':id11' => $row['id11']));

这很多打字,让我想知道我是否正确地进行了打字,但是我没有看到任何其他方式在线使用PDO进行大规模INSERT。

我简化了这个:

    //ConnectDB() is a method in another file that returns a PDO object
$dbHandle = ConnectDB();

/**
* Gets the columns of a MySQL table
* @param {String} $tableName is the name of the table
* @param {Object} $handle is the PDO object
* @return {array} returns a numeric array containing column names
*/
function getColumnNames($tableName, $handle) {
    $query = $handle->prepare("SHOW COLUMNS FROM $tableName");
    $query->execute();
    $table_fields = $query->fetchAll(PDO::FETCH_COLUMN);
    return $table_fields;
}

/**
* Builds an INSERT query using named placeholders
* @param {String} $tableName is the name of the table to be inserted
* @param {Object} $handle is the PDO object
* @return {String} returns a INSERT query
*/
function getColumnStrings($tableName, $handle) {

    $columnArray = getColumnNames($tableName, $handle);
    $size = sizeof($columnArray);
    $sql = "(";
    for($i = 0; $i < $size; $i++) {
        $sql .= $columnArray[$i] . ",";

    }
    $sql = rtrim($sql, ",");
    $sql .= ")";
    $values = "VALUES (";
    for($i = 0; $i < $size; $i++) {
        $values .= ":" . $columnArray[$i] . ",";

    }
    $values = rtrim($values, ",");
    $values .= ")";


    return "INSERT INTO " . $tableName . " ". $sql . " " . $values;

}

/**
* Builds an associative array to place inside query->execute()
* @param {array} $postArray numeric array containing $_POST values
* @param {Object} $handle is the PDO object
* @param {String} $tableName is the name of the table
* @return {array} returns an associative array with 
*                 values to be replaced
*/
function buildArr($postArray, $handle, $tableName) {
    $namesArray = getColumnNames($tableName, $handle);
    $size = sizeof($namesArray);
    $paramArray = [];
    for($i = 0; $i < $size; $i++) {
        $namesArray[$i] = ":" . $namesArray[$i];

    }

    for($i = 0; $i < $size; $i++) {
        $paramArray[$namesArray[$i]] = $postArray[$i];
    }

    return $paramArray;
}

我将命名的占位符放在一个数值数组中,然后在包含$_POST值的数组的同时循环遍历占位符数组,并创建一个新的关联数组放在$query->execute()参数中。

我也可以,而不是创建一个新数组,做bindValue()并绑定两个数组中的每个索引元素,我认为这将是另一种选择。我的方法是以正确的方式插入大量用户输入吗?

1 个答案:

答案 0 :(得分:1)

您的示例是一种方法,但我将举例说明我将如何处理此问题,尤其是当您可能有大量输入时,而不是经常需要更新SQL查询或数据库添加,删除或重新排序输入,或者不需要在接口和数据库之间创建不必要的依赖。

假设我们已经执行了任何我们想要进行的检查,我们知道要插入数组中的任何值,我会按照以下方式执行:

<?php
//This array gives us a way to match our incoming data to where it needs to be stored.
$lookup = array( 'form1' => 'id1', [...]);

$columns_params = array();
$params_values = array();

foreach($lookup as $form_key => $column_key) {
    $param_key = ':'.$column_key;
    $columns_params[$column_key] = $param_key;
    $params_values[$param_key] = $_POST[$form_key];
}

$insert_statement = sprintf('insert into some_other_table (%s) VALUES (%s)', implode(',',array_keys($columns_params)), implode(',',array_values($columns_params)));

$statement = $db->prepare($insert_statement);
array_map(function($param, $value) use (&$statement) {
                $statemnt->bindParam($param, $value);
            }, $params_values);
$statement->execute();