Подготовленный отчет PDO – синтаксис и дезинфекция

Я пытаюсь обновить мою базу данных следующим образом:

$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.

 $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"]))); 

Нет базы данных для меня, чтобы проверить, но это должен быть правильный путь.

Обратите внимание, что я просто следую вашему «стилю»; Несмотря на то, что этот код обрабатывает все $_POST качестве параметров и, таким образом, избегает инъекции SQL, он предполагает, что существует каждый $_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); 

Подготовленный оператор является подготовленным оператором, аргумент аргумента / параметр не рассматривается как 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 

У вас есть хорошая цель
Когда ваши поля выделены в белый список , этого достаточно для защиты (по сути, «белый список» – единственное правильное решение здесь).

Итак, единственное, что вам нужно – это получить правильный SQL из вашего белого списка и массива $ _POST.
Voila – вот полезная функция, написанная для этой цели .
с этим ваш код будет

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

(Пользовательские) функции великолепны. Не знаю, почему никто их не использует.