Mysqli 准备语句从数组动态构建 INSERT 查询

Mysqli prepared statements build INSERT query dynamically from array

我正在尝试在 PHP(不是 OOP)中开发我的功能,以创建一个 CRUD。目标是对任何 table 使用相同的函数,但我已经陷入了第一个。不知道该怎么做。

我现在拥有的:

// function to avoid injections
function validate($link, $field){
    $valid = mysqli_real_escape_string($link, $field);
    $valid = strip_tags($valid);
    return $valid;
}

// validate input of array
function sqlWithArray($link,$array){
    $return = array();
    foreach($array as $field=>$val){
        $return[$field] = "'".validate($link, $val)."'";
    }
    return $return;
}

// Multi insert to any table
function InsertDB($link, $table, array $args){
    $rows = sqlWithArray($link,$args);
    $keys = "(".implode(array_keys($args)," ,").")";
    $values = " VALUES (".implode(array_values($args),", ").")";
    $query = "INSERT INTO $table $keys $values";

    return $link->execute();
}

我尝试将其用作:

InsertDB($link, "test_table", $args); //$args is an array

但我不断收到以下错误:

PHP Fatal error:  Uncaught Error: Call to undefined method mysqli::execute() in includes\functions.php:37

我的37行是空的,但是36和38如下:

$query = "INSERT INTO $table $keys $values";

return $link->execute();

我哪里做错了?

拥有这样的功能本身就是一个好主意。它表明你在内心深处是一个程序员,而不仅仅是一个像乐高积木一样用现成的积木编写 PHP 的修补匠。这样的功能可以大大改进你的代码。

能力越大,责任越大。这样的函数是 通过 table 和字段名称 注入 SQL 的持续危险。你应该照顾好它。更不用说它应该使用准备好的语句为数据正确实施。

首先,您需要一个通用函数来使用查询和参数数组执行任意 MySQL 查询。我有一个简单的 mysqli helper function 给你。执行所有准备好的查询将是一个基本功能:

function prepared_query($mysqli, $sql, $params, $types = "")
{
    $types = $types ?: str_repeat("s", count($params));
    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    return $stmt;
}

现在我们可以开始动态构建 SQL 查询。为此,我们需要一个可以转义标识符的函数

function escape_mysql_identifier($field){
    return "`".str_replace("`", "``", $field)."`";
}

它将使标识符安全,至少只要您使用 Unocode。

现在我们可以继续创建正确的 SQL 字符串。我们需要创建一个带有占位符的 SQL,如下所示:

INSERT INTO `staff` (`name`,`occupation`) VALUES (?,?)

所以让我们编写一个函数来创建这样的查询

function create_insert_query($table, $keys)
{
    $keys = array_map('escape_mysql_identifier', $keys);
    $fields = implode(",", $keys);
    $table = escape_mysql_identifier($table);
    $placeholders = str_repeat('?,', count($keys) - 1) . '?';
    return "INSERT INTO $table ($fields) VALUES ($placeholders)";
}

终于可以写出寻找已久的 crud 函数了:

function crud_insert($conn, $table, $data) {
    $sql = create_insert_query($table, array_keys($data));
    prepared_query($conn, $sql, array_values($data));
}

这样称呼

$args = ['name' => "D'Artagnan", "occupation" => 'musketeer'];
crud_insert($link, "test_table", $args);