Создание оператора INSERT для всех переменных $_POST в массиве

Мы все знакомы с традиционной обработкой форм, т.е.

$электронная почта = $_POST['электронная почта']; $имя = $_POST['имя'];

и т. д., а затем мы получаем все переменные из сообщения. а затем мы создадим составной оператор, например

$qry = "INSERT INTO $tableName (email,name) values ('$email','$name')";

Что если бы у вас было 18-20 вопросов? большинство людей просто пишут строки и строки кода. 99,9% всех пользователей сети делают это снова и снова.

Давай попробуем что-нибудь другое? Я понял, что должен быть лучший способ использования массивов.

В течение многих лет я искал простую процедуру и везде искал ее, которая будет СОЗДАВАТЬ оператор вставки ИЗ всех переменных $_POST.

До меня дошло, что $_POST на самом деле является массивом, поэтому я написал этот небольшой скрипт:

$vars = $_POST;
print_r($vars);
exit;

После нескольких часов работы с людьми на этом форуме вот полученный код. Я считаю, что создание контрольной суммы хэша всех ключей массива избавит от опасений SQL-атак, поскольку сервер не вызывается, пока не получит точное совпадение. Если кто-то добавит поле, это не удастся. Все согласны?

$predefinedChecksum = "84e602bbec8124f298e353171fb7f5b2"; // this is the hash value of all the array keys
$keys = array_keys($_POST);
$values = array_values($_POST);
$sql = "INSERT INTO $tableName (" . join(',', $keys) . ") VALUES ('" . join("',", $values) . "');";
$checksum = md5(join(',',$keys));
if ($checksum<>$predefinedChecksum) exit;
else $res = mysql_query($qry, $conn);

Спасибо всем, кто внес свой вклад... Думаю, у нас получился отличный сценарий.

Кто-то упомянул, чтобы отключить «кнопку» - как вы это делаете?

unset( $_POST['button'] );

Это не сработало — вывод скрипта по-прежнему показывает «кнопку» в качестве одной из переменных. Таким образом, вывод скрипта по-прежнему имеет поле под названием «кнопка» в конце.

Я не уверен, как вы могли бы удалить его из серии $values ​​У кого-нибудь есть идеи?

Также выход

ВСТАВЬТЕ В (nameFirst, nameLast, emailPref, emailAlt, phoneDay, phoneMobile, этническая принадлежность, род деятельности, доход, семейный, дети‹18, образование, занятость, компания, название, отрасль, отдел, revAnnual, numemps, улица, город, штат, почтовый индекс ,Type_Mobile,планшет,компьютер,ноутбук) VALUES ('Vik',Grant',[email protected]',',',',african',',19',single',',Some_HS',student', ',',Finance_Accntg',Admin',',',',',',',Android',',',');

отсутствует ' кавычка в начале значения - может ли соединение существовать как соединение (a, b, c)?


person Viktor    schedule 29.05.2014    source источник
comment
я предлагаю использовать класс базы данных, такой как Zend_Db_Adapter   -  person Peter    schedule 29.05.2014
comment
Я бы ОЧЕНЬ опасался внедрения SQL, если вы пытаетесь найти способ получить ваши переменные $_POST прямо в операторе вставки...   -  person Pudge601    schedule 29.05.2014
comment
Я тоже хотел сделать что-то подобное. Это то, за чем я в конце концов последовал: database">stackoverflow.com/questions/11611631/ Это хорошее решение   -  person asprin    schedule 29.05.2014
comment
Хорошая точка зрения. Давайте сначала посмотрим, может ли кто-нибудь на этом форуме написать инструкцию INSERT. Я недостаточно хорошо разбираюсь в PHP, чтобы написать этот оператор INSERT. Тогда мы можем беспокоиться о его защите. Я бы защитил его от SQL-атак, проверив имена полей и сравнив эту контрольную сумму с правильной. Ради скорости (и весь смысл этого вопроса) - предоставить онлайн-сообществу фрагмент кода, который каждый может использовать в любое время, когда ему не хочется указывать ТОЧНЫЕ имена полей.   -  person Viktor    schedule 29.05.2014
comment
Поэтому выше я внес некоторые изменения и контрольную сумму. Эта контрольная сумма жестко закодирована в сценарии и сравнивается с фактической контрольной суммой имен полей. Это должно предотвратить любые атаки SQL-инъекций. Если кто-то попытается добавить поле, он просто выйдет. Решит ли это опасения, связанные с SQL-инъекциями?   -  person Viktor    schedule 29.05.2014
comment
Имейте в виду, что расширение mysql (предоставляющее функции mysql_) устарело с 2012 года в пользу расширений mysqli и PDO. Его использование крайне не рекомендуется. См. stackoverflow.com /вопросы/12859942/   -  person Oldskool    schedule 29.05.2014


Ответы (4)


Просто зациклите его с помощью foreach http://nl1.php.net/manual/en/control-structures.foreach.php будьте осторожны, так как это позволяет перезаписать любой столбец. Безопаснее указать, какие столбцы разрешено вставлять.

И, пожалуйста, используйте что-то вроде PDO для использования подготовленных операторов.

person Chris    schedule 29.05.2014
comment
Читай выше. Правильный способ - сделать цикл for_each - я просто не знаю, как написать этот цикл таким образом, чтобы он правильно указывал столбцы $qry = INSERT INTO $tableName (email,name) values ​​('$email' ,'$имя'); также это оператор INSERT, а не оператор UPDATE. - person Viktor; 29.05.2014

Вы действительно не хотите этого делать, поскольку вы генерируете запросы, которые могут быть изменены клиентом.

Но чтобы ответить на ваш вопрос, вы можете сделать что-то вроде:

$columns = array("email", "name", "etc.."); // Array with the "good" columns.

// Unset the columns you do not want in your query.
foreach($_POST as $key=>$value){
    if(!in_array($key, $columns)){
        unset($_POST[$key]);
    }
}

$qry = "INSERT INTO " . $tableName . " (" . implode(", ", array_keys($_POST)) . ") values (" . implode("', '", array_values($_POST)) . ")";
person user1961685    schedule 29.05.2014
comment
На самом деле мы хотим генерировать запросы, которые клиент может изменить, в этом весь смысл упражнения. Я могу преодолеть проблемы безопасности с помощью контрольной суммы MD5 столбцов имени поля. На данный момент давайте не будем беспокоиться о безопасности, давайте просто посмотрим, возможно ли создать оператор вставки, который делает то, что задано в вопросе. Спасибо! - person Viktor; 29.05.2014

Хотя обычным способом является использование цикла для создания строки, содержащей ваши значения, я иногда делаю следующее, когда знаю точный порядок ключей в моем массиве:

$arr = array(
   "email"=>"[email protected]",
   "name"=>"vlzvl"
);
$sql = "INSERT INTO mytable (email,name) VALUES ('".implode("','",$arr)."')";
person Community    schedule 29.05.2014
comment
да - это хорошо - и то, что я пытался сделать, НЕ определяло массив в PHP - массив и имена полей определяются в самой ФОРМЕ. он же отзывчивый. Мне нравится то, что вы написали, однако это еще раз не извлекает имена полей из массива - вы определяете адрес электронной почты, имя - person Viktor; 29.05.2014

вы не должны этого делать, так как это огромная проблема безопасности.

Но если вы действительно хотите это сделать: (непроверено, вы все еще можете внедрить SQL, так что это небезопасно!)

$keys = array_keys($_POST);
$values = array_values($_POST);

$sql = "INSERT INTO $tableName (" . join(',', $keys) . ") VALUES ('" . join("',", $values) . "');";

Редактировать:

Если вы используете PDO, вы можете сделать это так:

$keys = array_keys($_POST);
$values = array_values($_POST);

$valuePlaceholders = "";

for ($i=0; $i < count($_POST); $i++) {
    $valuePlaceholders .= $i === 0 ? '?' : ', ?';
}

$sql = "INSERT INTO $tableName (" . join(',', $keys) . ") VALUES ($valuePlaceholders);";

И при выполнении $pdo->execute($values);

person Janne Savolainen    schedule 29.05.2014
comment
Лол… никогда не знал, что join — это псевдоним implode. Также вы можете рассмотреть возможность отключения кнопки отправки - person asprin; 29.05.2014
comment
Позвольте мне проверить это - пока это лучшая идея. Ребята, так просто защитить это от SQL-инъекций с помощью хэштега MD5. Как только я найду, что это работает, я опубликую код. - person Viktor; 29.05.2014
comment
Оно работает! Итак, чтобы решить проблему SQL-инъекций, я сделал следующее: $checksum = md5(join(',',$keys)); напечатать контрольную сумму $; Каждая уникальная форма имеет набор значений, которые генерируют контрольную сумму. Я жестко закодировал эту контрольную сумму в форму. Пока контрольная сумма совпадает, форма отправляется нормально — если она не совпадает, мы знаем, что это была SQL-инъекция, и скрипт просто завершает работу. Спасибо, Янне - прекрасно сработало Первая строка скрипта сравнит - person Viktor; 29.05.2014
comment
Очень близко — оператор SQL не будет отправлен, потому что значения должны быть заключены в кавычки. Любые идеи? - person Viktor; 29.05.2014
comment
Ой, извини. Это была моя ошибка. Измените это VALUES (" . join(',', $values) ."); на VALUES ('" . join("',", $values) . "'); - person Janne Savolainen; 29.05.2014
comment
1. Так нельзя установить NULL. - person DarkSide; 29.05.2014
comment
3. Хэштег MD5 в данном случае бесполезен и ничего вам не даст. Те же результаты вы можете получить, проверяя только хорошие ключи на стороне сервера перед вставкой значений в БД. Проще говоря - MD5 должен быть сгенерирован на стороне сервера, чтобы избежать хакеров вашей формы. Как вы можете сгенерировать этот md5 на сервере, если вы не знаете ключей заранее? Правильно, вы должны знать свои ключи, и если вы это сделаете, вы можете просто проверить только разрешенные ключи, когда пользователь отправляет свою форму. В результате нет необходимости в MD5. - person DarkSide; 29.05.2014
comment
1. Правда, sql надо создавать с циклами, чтобы можно было ставить NULL. 2. Конечно, есть еще способ внедрить SQL в значения. Как я уже сказал в ответ, это проблема безопасности. - person Janne Savolainen; 29.05.2014
comment
Вы генерируете MD5 один раз перед запуском формы. Жестко закодируйте его в скрипт, пока вы не измените форму, хэш-тег останется прежним. Дело в том, что полученная форма будет содержать 30-50 вопросов и будет постоянно меняться. Мы не хотим постоянно менять имена полей и имена запросов. Итак, есть необходимость в MD5 - чтобы сравнить, добавил ли кто-то поле, которого не должно было быть в массиве $_POST Тем не менее - скрипт не закончен, потому что форматирование неправильное - без кавычек на значениях на с обеих сторон он не будет ВСТАВЛЯТЬ - person Viktor; 29.05.2014
comment
Я обновил свой ответ, чтобы добавить кавычки к значениям. Вы пробовали это? - person Janne Savolainen; 29.05.2014