Intereting Posts
Наследование PHP, родительские функции с использованием дочерних переменных Подтвердите кнопку перед запуском процедуры удаления с веб-сайта Выбор нескольких параметров в ячейках выбора и получение результатов из базы данных? Как объединить 3 массива в один большой массив (те же ключи) Невозможно создать временный файл в PHP, несмотря на то, что существует каталог temp Предотвратить установку даты PHP () от дефолта до 12/31/1969 Как обращаться с диакритикой (акцентами) при переписывании «хороших URL-адресов» Как правильно загрузить jQuery в WordPress Контейнер для тортов 2.2.1: Ошибки испеки Получить множество значений с помощью ajax из get in php как установить openssl для php 5.3.5 на windows xp? Каков наилучший способ перевода системы перевода на веб-сайт php? Функция substring_index в доктрине ORM Доктрина: обновление дискриминатора для SINGLE_TABLE Наследование Исключение определенного шаблона из выражения регулярного выражения

Объединение подготовленного оператора в функцию

Я читал статьи о SQL Injection и решил изменить свой код, чтобы предотвратить SQL-инъекцию.

Например, у меня есть вход, который я вставляю в мою базу данных. Первоначально моя защита от инъекций была такой:

function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); // $data = addslashes($data); $data = mysql_real_escape_string($data); return $data; } $artist = $_POST["artist"]; // can be anything $artist = test_input($artist); // escaped chars are &, quotes, <, >, \n, \r, etc. if ($mysqli->query("SELECT * FROM `my_table` WHERE `artist` = '$artist'")->num_rows == 0) { $mysqli->query("INSERT INTO my_table (artist) VALUES ('$artist')"); echo "New artist is added."; } else { echo "Artist already exists."; } 

В статьях, которые я прочитал, было предложено использовать подготовленные заявления. Я изменил свой код и использовал его:

 $artist = $_POST["artist"]; // can be anything $query = $mysqli->prepare("SELECT * FROM my_table WHERE artist = ?"); $query->bind_param("s", $artist); $query->execute(); $result = $query->get_result(); $query->close(); if ($result->num_rows == 0) { echo "Artist doesn't exist in the DB." . PHP_EOL; $query = $mysqli->prepare("INSERT INTO my_table (artist) VALUES (?)"); $query->bind_param("s", $artist); $query->execute(); if ($query->affected_rows > 0) { echo "Artist is added to the DB." . PHP_EOL; } $query->close(); } else { echo "Artist already exists in the DB." . PHP_EOL; } 

Хотя это предотвращает внедрение SQL, оно ничего не делает для XSS. Поэтому я решил изменить test_input (удалил $data = mysql_real_escape_string($data); ) и использовал его, чтобы предотвратить инъекцию скрипта.

 function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data; } $artist = $_POST["artist"]; // can be anything $artist = test_input($artist); 

Теперь моя проблема заключается в использовании подготовленных операторов. Я буду вставлять три элемента; исполнителя, альбома и песни. Повторение одного и того же процесса (подготовка, привязка, выполнение, закрытие) снова и снова кажется излишним для меня. Я хочу создать функцию и перенести с ней подготовленный процесс утверждения. Что-то вроде этого:

 function p_statement($mysqli, $query_string = "", $type = "", $vars = []) { $query = $mysqli->prepare($query_string); $query->bind_param($type, $vars); $query->execute(); $result = null; preg_match("/^[AZ]+/", $query_string, $command); switch ($command[0]) { case "SELECT": $result = $query->get_result(); break; case "INSERT": $result = $query->affected_rows; break; } $query->close(); return $result; } 

Хотя, это представляет проблему: $vars array. Поскольку число переменных, которые будут переданы mysqli_stmt::bind_param() будет переменным / динамическим, я использовал массив в основной функции p_statement . Я не знаю, как мне передать элементы массива в mysqli_stmt::bind_param() . bind_param ожидает (type, var1, var2, varn,) , и у меня есть массив.

Как я могу сделать эту работу?

Вы ищете implode()

Глядя на man- call_user_func_array он показывает, как использовать call_user_func_array . И я редактирую часть вашего фрагмента.

 function p_statement($mysqli, $query_string = "", $type = "", $vars = []) { $query = $mysqli->prepare($query_string); //assign $type to first index of $vars array_unshift($vars, $type); //Turn all values into reference since call_user_func_array //expects arguments of bind_param to be references //@see mysqli::bind_param() manpage foreach ($vars as $key => $value) { $vars[$key] =& $vars[$key]; } call_user_func_array(array($query, 'bind_param'), $vars); $query->execute(); //INSERT, SELECT, UPDATE and DELETE have each 6 chars, you can //validate it using substr() below for better and faster performance if (strtolower(substr($query_string, 0, 6)) == "select") { $result = $query->get_result(); } else { $result = $query->affected_rows; } $query->close(); return $result; } 

Я нашел способ решить проблему, используя call_user_func_array .

 function p_statement($mysqli, $query_string = "", $type = "", $vars = []) { $query = $mysqli->prepare($query_string); // create an empty array $parameters = array(); // push the type string into the array by reference $parameters[] = & $type; // push the items from $vars array into the array by reference for ($i = 0; $i < count($vars); $i++) { $parameters[] = & $vars[$i]; } // call mysqli_stmt::bind_param with the $parameters array, which contains [type, var1, var2, ...] call_user_func_array(array($query, "bind_param"), $parameters); $query->execute(); $result = null; preg_match("/^[AZ]+/", $query_string, $command); switch ($command[0]) { case "SELECT": $result = $query->get_result(); break; case "INSERT": case "UPDATE": case "DELETE": $result = $query->affected_rows; break; } $query->close(); return $result; } 

 $artist = "3 Doors Down"; $year = 2000; $artist_select = p_statement($mysqli, "SELECT * FROM albums WHERE artist = ? AND year = ?", "si", [$artist, $year]); var_dump($artist_select->fetch_all(MYSQLI_ASSOC)); 

Выходы:

 array(1) { [0]=> array(3) { ["album"]=> string(15) "The Better Life" ["year"]=> int(2000) ["artist"]=> string(12) "3 Doors Down" } }