通过使用 Common Function 在 PHP 中准备绑定参数来更新 SQL 表

Update SQL table by prepare binding parameters in PHP using a Common Function

提问人:musab 提问时间:11/1/2022 最后编辑:Dharmanmusab 更新时间:11/2/2022 访问量:204

问:

我致力于在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数组,外侧功能?所以我可以传递有关提交表单的不同参数?

php mysqli 预备语句

评论

1赞 Dharman 11/1/2022
您可以在 What's wrong with that?update_table($tablename,$creteria,$params)
2赞 Your Common Sense 11/2/2022
@Dharman实际上,有很多错误。$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的新手,我不知道为什么有些开发人员会告诉你你的方式不好。但是你能按照他们的建议发烧来改变功能吗?