0

我正在尝试使用以下内容更新我的数据库:

$fields = array(
    'titulo',
    'tipo_produto',
    'quantidade_peso',
    'unidade_de_venda',
    'unidades_por_caixa',
    'caixas_piso',
    'pisos_palete',
    'tipo_palete',
    'unidades_palete',
    'caixas_palete',
    'uni_diametro',
    'uni_largura',
    'uni_profundidade',
    'uni_altura',
    'caixa_largura',
    'caixa_profundidade',
    'caixa_altura',
    'altura_palete',
    'volume_unidade',
    'volume_caixa',
    'volume_palete',
    'peso_caixa',
    'peso_palete'
);
$sql = 'UPDATE ficha_item SET '.implode(', ', array_map(create_function('$value', 'return "$value=\"" . $_POST["$value"] ."\"";'), $fields)).' WHERE id=?';

$stmt = $db->prepare($sql);

$stmt->execute(array($_POST['item_id']));
$stmt->closeCursor();

这似乎工作得很好,但我想知道安全性,这是否经过消毒?

在尝试(没有成功)另一个解决方案后,我想出了这个解决方案:

$fields = array(
    'titulo',
    'tipo_produto',
    'quantidade_peso',
    'unidade_de_venda',
    'unidades_por_caixa',
    'caixas_piso',
    'pisos_palete',
    'tipo_palete',
    'unidades_palete',
    'caixas_palete',
    'uni_diametro',
    'uni_largura',
    'uni_profundidade',
    'uni_altura',
    'caixa_largura',
    'caixa_profundidade',
    'caixa_altura',
    'altura_palete',
    'volume_unidade',
    'volume_caixa',
    'volume_palete',
    'peso_caixa',
    'peso_palete'
);
$sql = 'UPDATE ficha_item SET ? WHERE id=?';

$valuesClause = implode(', ', array_map(create_function('$value', 'return "$value=\"" . $_POST["$value"] ."\"";'), $fields));

$stmt = $db->prepare($sql);

$stmt->execute(array($valuesClause, $_POST['item_id']));
$stmt->closeCursor();

完全没有错误,但我的数据库不会更新。我的第一个解决方案完全消毒了吗?我最初的想法出了什么问题?我认为这与 PDO 如何在执行时清理查询有关......但我不知道该去哪里。

注意:数据库列名称和输入名称相同,这就是$value有效的原因。如果您还想知道,由于 PHP 版本是实时的,匿名函数是不可能的。

4

3 回答 3

2

准备好的语句是准备好的语句,由于显而易见的原因,语句参数/参数不被视为 SQL。

在准备语句之前,您需要准备查询。

我建议你阅读PDO手册。您还应该查看这个问题,以了解如何保护您的查询。

$columns = array();
foreach ($fields as $column)
    $columns[] = "$column = ?";

$sql = "UPDATE table SET " . implode(" AND ", $columns) . " WHERE id = ? ";

// Now you may prepare the statement
于 2013-01-07T11:37:15.523 回答
1
$fields = array(
    'titulo',
    'tipo_produto',
    'quantidade_peso',
    'unidade_de_venda',
    'unidades_por_caixa',
    'caixas_piso',
    'pisos_palete',
    'tipo_palete',
    'unidades_palete',
    'caixas_palete',
    'uni_diametro',
    'uni_largura',
    'uni_profundidade',
    'uni_altura',
    'caixa_largura',
    'caixa_profundidade',
    'caixa_altura',
    'altura_palete',
    'volume_unidade',
    'volume_caixa',
    'volume_palete',
    'peso_caixa',
    'peso_palete'
);
$sql="UPDATE ficha_item SET ".implode(", ",array_map(function($s){
    return "$s = ?";
},$fields))." WHERE id=?";
print_r($sql);

输出:

UPDATE ficha_item SET titulo = ?, tipo_produto = ?, quantidade_peso = ?, unidade_de_venda = ?, unidades_por_caixa = ?, caixas_piso = ?, pisos_palete = ?, tipo_palete = ?, unidades_palete = ?, caixas_palete = ?, uni_diametro = ?, uni_largura = ?, uni_profundidade = ?, uni_altura = ?, caixa_largura = ?, caixa_profundidade = ?, caixa_altura = ?, altura_palete = ?, volume_unidade = ?, volume_caixa = ?, volume_palete = ?, peso_caixa = ?, peso_palete = ? WHERE id=?

这是您需要的SQL 语句prepare。现在得到你准备好的声明

$stmt=$db->prepare($sql);
$stmt->execute(array_merge(array_map(function($s){
    return $_POST[$s];
},$fields),array($_POST["item_id"])));

没有数据库供我测试,但这应该是正确的轨道。

请注意,我只是遵循您的“风格”;尽管此代码将 all$_POST视为参数,从而避免了 SQL 注入,但它假设 every$_POST[$fields[$idx]]存在,任何用户都可以轻松破坏,所以这是你应该清理的地方。

编辑

由于您已更新不能使用匿名函数,因此您可以手动构造所需的数组:

$cache=array();
foreach($fields as $field)
    $cache[]="$field = ?";
$sql="UPDATE ficha_item SET ".implode(", ",$cache)." WHERE id=?";

$cache=array();
foreach($fields as $field)
    $cache[]=isset($_POST[$field])?$_POST[$field]:null;
$cache[]=$_POST["item_id"]
/*...*/
$stmt->execute($cache);
于 2013-01-07T11:58:06.570 回答
1

你有一个很好的目标
当你的字段在你的代码中被列入白名单时,这足以保护(事实上。白名单是这里唯一合适的解决方案)。

因此,您唯一需要做的就是从白名单和 $_POST 数组中获取正确的 SQL。
瞧——这里是为此目的而编写的一个有用的函数
有了它,您的代码将成为

$sql  = "UPDATE ficha_item SET ".pdoSet($fields,$values)." WHERE id = :id";
$stmt = $db->prepare($sql);
$values["id"] = $_POST['id'];
$stmt->execute($values);

(用户定义的)功能很棒。不知道为什么没有人使用它们。

于 2013-01-07T12:06:03.017 回答