Немного о подготавливаемых запросах PHP
В этой небольшой заметке я расскажу о подготавливаемые запросах и том, как их создавать на PHP для расширения MySQLi.
Как обычно вообще новички пишут код для работы с базой данных на языке PHP? Как правило, все начинается с чего-то подобного:
$db = mysql_connect ("localhost","bd_user","passowrd"); @mysql_query("SET NAMES utf8"); @mysql_query("SET CHARACTER SET utf8"); @mysql_query("SET character_set_client = utf8"); @mysql_query("SET character_set_connection = utf8"); @mysql_query("SET character_set_results = utf8"); mysql_select_db ("bd_name",$db); $result = mysql_query("SELECT * FROM table WHERE id=$id",$db); $myrow = mysql_fetch_array($result);Дальше уже начинающий программист начинает осваивать расширения PHP и знакомится с MYSQLi и/или PDO. И уже начинает писать как-то так
$conn = new mysqli("localhost", " bd_user", " passowrd", " bd_name"); $conn ->set_charset("utf8"); if ($conn->connect_error) die("Ошибка: невозможно подключиться: " . $conn->connect_error); $query = "INSERT INTO `table` (`name`) VALUES ('$name');"; mysqli_query($conn, $query) or die (mysqli_error($conn));Потом сталкивается с тем, что иногда в данных имеются апострофы и начинает использовать такие конструкции перед вставкой
$txt_esc = $conn->real_escape_string($txt);Потом узнает об SQL инъекциях и начинает проверять данные перед выполнением запросов. Приводит их к типу int(если числа), убирает подозрительные символы и конструкции и так далее. И, наконец, приходит к подготавливаемым запросам. Такие запросы работают с любыми символами, имеют защиту от инъекций, да и просто удобны. Вот как, например, можно получить информацию (SELECT)
$sql = "SELECT * FROM table WHERE id = ? "; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $id); $stmt->execute(); $result = $stmt->bind_result(); $rows = $result->fetch_all(MYSQLI_ASSOC);Или так
function prepared_query($mysqli, $sql, $params, $types = ""){ $types = $types ?: str_repeat("s", count($params)); $stmt = $mysqli->prepare($sql); $stmt->bind_param($types, ...$params); $stmt->execute(); return $stmt; } function get_file($name){ global $conn; $film = array(); $sql = "SELECT * FROM files WHERE name = ? LIMIT 1"; $stmt = prepared_query($conn, $sql, [$name]); if ($row = $stmt->get_result()->fetch_assoc()){ $film = $row; } return $film; }А так вставить строку
function insert_film($name){ global $conn; $stmt = $conn->prepare("INSERT INTO `films` (`name`) VALUES (?)"); $stmt->bind_param("s", $name); if ($stmt->execute()) { $id = $conn->insert_id; } $stmt->close(); return $id; }Теперь ложка дегтя. Не всегда подготавливаемые запросы можно использовать и даже в серьезных проектах не везде они встречаются, хотя и обладают рядом существенных достоинств. Почему? Основная причина – их сложно менять динамически.
То есть, например, берем мы запрос поиска с набором параметров, заранее неизвестных и что делать? В случае обычного запроса мы просто меняем переменную, генерируем её сами по полям (AND AND AND) , подставляем и выполняем. А для подготавливаемого так не получится.
В общем, тут как обычно в программировании – для каждой ситуации используется свой инструмент.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.