提问人:musab 提问时间:11/1/2022 最后编辑:Dharmanmusab 更新时间:11/2/2022 访问量:204
通过使用 Common Function 在 PHP 中准备绑定参数来更新 SQL 表
Update SQL table by prepare binding parameters in PHP using a Common Function
问:
我致力于在PHP中制作一个通用函数来更新表,因为我有很多表单更新MySQL表。它工作正常,它更新了我的表格:下面是我的代码和一些注释:
<?php
include('../config.php');
if (isset($_POST['loginfo'])) {
$table = "users";
$creteria = "id =?";
if (update_table($table,$creteria)){
echo "<h1> Successfully Updated Table: ". $table. "</h1>";
}
}
function update_table($tablename,$creteria) {
$conn = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "UPDATE ".$tablename. " SET ";
$postdata = $_POST;
$count = count($postdata);
$nonempty = count(array_filter($postdata, function($x) { return ($x !== ""); }));
$i = 0;
$vartype = "";
foreach ($postdata as $key => $value) {
$i++;
if (!empty($value)) {
$nonempty--;
$sql .= " $key = ? ";
if ($nonempty >0) {
$sql .= " ,";
}
if(is_int($value)){
$vartype .= "i";
} else {
$vartype .= "s";
}
}
}
$sql .= "WHERE ".$creteria;
$vartype .= "i";
$stmt = $conn->prepare($sql);
$params = array(&$fullname, &$email, &$phone, &$id);// this line must be out side function
call_user_func_array(array($stmt, "bind_param"), array_merge(array($vartype), $params));
$fullname = $_POST['fullname']; // fullname,email,phone, id must be out of function
$email = $_POST['email'];
$phone = $_POST['phone'];
$id = $_POST['id'];
$stmt->execute();
$stmt->close();
$conn->close();
return true;
}
?>
如何把$params数组,外侧功能?所以我可以传递有关提交表单的不同参数?
答:
-1赞
Tural Rzaxanov
11/1/2022
#1
您可以使用 params 变量作为全局变量。你可以合并或直接用区间变量等于它们,在函数内部。例如:
$paramsGlobal = ['name'=> 'Tural Rza'];
function update_table($tablename,$creteria) {
global $paramsGlobal;
$conn = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "UPDATE ".$tablename. " SET ";
$postdata = $_POST;
$count = count($postdata);
$nonempty = count(array_filter($postdata, function($x) { return ($x !== ""); }));
$i = 0;
$vartype = "";
foreach ($postdata as $key => $value) {
$i++;
if (!empty($value)) {
$nonempty--;
$sql .= " $key = ? ";
if ($nonempty >0) {
$sql .= " ,";
}
if(is_int($value)){
$vartype .= "i";
} else {
$vartype .= "s";
}
}
}
$sql .= "WHERE ".$creteria;
$vartype .= "i";
$stmt = $conn->prepare($sql);
$params = array_merge(array(&$fullname, &$email, &$phone, &$id),$paramsGlobal);// this line must be out side function
call_user_func_array(array($stmt, "bind_param"), array_merge(array($vartype), $params));
$fullname = $_POST['fullname']; // fullname,email,phone, id must be out of function
$email = $_POST['email'];
$phone = $_POST['phone'];
$id = $_POST['id'];
$stmt->execute();
$stmt->close();
$conn->close();
return true;
}
?>
评论
0赞
Your Common Sense
11/2/2022
你不应该像这样使用全局 stackoverflow.com/a/12446305/285587
0赞
Your Common Sense
11/2/2022
此外,您的代码并不能解决实际问题
0赞
Veshraj Joshi
11/1/2022
#2
我重写了你的函数,并且对我来说工作正常,你可以检查一下。在代码中,条件仍然容易受到 SQLIA 攻击。因此,以下是 等效代码使用以下条件更新任何表 -
function update_table(string $tablename,array $criteria, array $updateData) {
$params = array_merge(array_values($updateData), array_values(reset($criteria)));
try {
$conn = new PDO(sprintf('mysql:dbname=%s;host=%s', DB_DATABASE, DB_HOSTNAME),
DB_USERNAME,
DB_PASSWORD);
$updateLastKey = array_key_last($updateData);
$sql = sprintf("UPDATE %s SET ", $tablename);
foreach($updateData as $key => $item) {
$sql = sprintf("%s %s = ?%s ", $sql, $key,$key == $updateLastKey? "" : "," );
}
$sql = sprintf("%s WHERE %s", $sql, key($criteria));
$stmt = $conn->prepare($sql);
$stmt->execute($params);
$conn = null;
} catch (PDOException $e){
die($e->getMessage());
}
return true;
}
现在您可以按如下方式调用上述函数 -
$updateData = ["name"=>$_POST['name'], "price"=> $_POST['price']];
$criteria = ["category_id = ? and price>=? " => [1, 500]];
update_table('products',$criteria,$updateData);
// this will update all the products whose category id is 1 and price is greater than 500
注意:我认为使用PDO比mysqli更好
评论
0赞
Dharman
11/1/2022
foreach($updateData as $key => $key)
这是怎麽?
1赞
Your Common Sense
11/2/2022
PDO确实更好,但这个功能在很多层面上仍然是错误的。不得有新的 PDO、不得有 die($e->getMessage())、不得$databaseName
3赞
Your Common Sense
11/2/2022
更重要的是,因此功能是相当无用的。同样的事情也可以做到,更少的代码更容易阅读 100 倍,而prepared_query更短 10 倍,更通用。prepared_query($db, "UPDATE products SET name=?, price=? WHERE category_id = ? and price>=?", [$_POST['name'],$_POST['price'],1,500]);
0赞
Veshraj Joshi
11/2/2022
@YourCommonSense同意你的看法。这是为了防止有人大部分时间都不想看到原始查询。以您的方式,代码也更有效率,因为没有关于映射的进一步处理。
1赞
musab
11/4/2022
@VeshrajJoshi,您的代码适用于所有表单和表格。由于我是PHP的新手,我不知道为什么有些开发人员会告诉你你的方式不好。但是你能按照他们的建议发烧来改变功能吗?
评论
update_table($tablename,$creteria,$params)