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);
我正在尝试在 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);