0

我在我的 MySQL 数据库中创建了 TINYINT 列来解释布尔变量,该变量基于 html 中是否选中复选框,将值(0 表示假,其他所有内容表示真)存储在数据库中。但是当调用 php 文件时它不会更新值。我的 SQL 有问题吗?TINYINT 是否输入如下?简单地用一个0和一个1?

<?php
include_once("createConnection.php");
session_start();
$checkbox = $_POST['name'];
$checked = $_POST['checked'];
$currentUser = $_SESSION['validUser'];

if($checked=='yes'){
    $request='UPDATE projectDB.Members 
        SET :name=1 WHERE username=:currentUser';
    $preparedStatement = $bdd->prepare($request); 
    $preparedStatement->bindParam(':name', $checkbox, PDO::PARAM_STR);
    $preparedStatement->bindParam(':currentUser', $currentUser, PDO::PARAM_STR);
    $preparedStatement->execute();
}
else{
    $request='UPDATE projectDB.Members 
        SET :name=0 WHERE username=:currentUser';
    $preparedStatement = $bdd->prepare($request); 
    $preparedStatement->bindParam(':name', $checkbox, PDO::PARAM_STR);
    $preparedStatement->bindParam(':currentUser', $currentUser,     PDO::PARAM_STR);
    $preparedStatement->execute();
}
?>
4

1 回答 1

0

通常,当您接受用户输入时,您希望像这样参数化您的查询。您的问题是您正在接受的用户输入(或至少是潜在的用户输入)是列名而不是值。PHP 正在将您的查询转换为如下内容:

UPDATE projectDB.Members 
    SET 'name'=1 WHERE username='currentUser'

哪个不符合您的要求(它告诉 SQL 更新一个名为 'name' 的字符串,而不是更新一个名为 的列name)。

如果您不清理数据,您仍然会有风险 - 您基本上有两种选择:

在你的代码中有一个可接受的列名的白名单;验证传入的字符串是否与该白名单中的条目完全匹配,如果是,则将其用作列名。这里的缺点是您的数据模型中的列名散布在您的代码和 HTML 上。例如:

$chkcols['name1'] = true;
$chkcols['name2'] = true;
$chkcols['name3'] = true;

...
if ($chkcols[name] == true) ...;

或者

想出一个不同的数据模型,比如 EAV,你不必处理动态列名。这里的缺点是 EAV 在 SQL 中可能有点反模式。这可能会使用类似的查询 UPDATE projectDB.Members SET Enabled = 1 WHERE name=:name AND username =:currentUser:除了 EAV 模型之外,您还可以拥有一个具有首选项或某种位掩码/列表的列(但同样,这是一个 SQL 反模式,因为您试图将多条信息打包在一个列中。

于 2017-03-12T02:37:08.117 回答