PHP5 MySQL Подготовленные заявления
Подготовленные заявления очень полезны для инъекций SQL.
MySQLi Подготовленные заявления и связанные параметры
Подготовленные заявления - это функция, используется для выполнения одних и тех же (или аналогичных) заявлений SQL неоднократно, с высокой эффективностью.
Подготовленные заявления в основном работают:
- Подготовка: шаблон SQL оператор будет создан и отправлен в базу данных.
Определенные значения остаются неопределенными, называемыми параметрами (помечены
"?"
). Пример: INSERT INTOMyGuests
VALUES(?, ?, ?)
- База данных разбирает, собирает и выполняет оптимизацию запросов к шаблону заявлений SQL и сохраняет результат, без выполнения
- Выполнение: на более позднее время, приложение связывает значения параметров и базы данных выполняет заявление. Приложение может выполнять заявление столько раз, сколько он хочет с различными значениями
По сравнению с непосредственным выполнением заявлений SQL, подготовленные заявления имеют три основных преимущества:
- Подготовленные заявления сокращают время синтаксического анализа, так как подготовка к запросу выполняется только один раз (хотя заявление выполняется несколько раз)
- Связанные параметры минимизируют пропускную способность сервера, так как необходимо отправлять только параметры каждый раз, а не весь запрос
- Подготовленные заявления очень полезны для инъекций SQL, так как значения параметров, передаваемые позже по другому протоколу, могут быть не правильно экранированы. Если исходный шаблон инструкции не является производным от внешнего ввода, инъекция SQL не может проявляться.
MySQLi Подготовленные заявления
В следующем примере используются подготовленные заявления и связанные параметры в MySQLi:
Пример MySQLi - с подготовленным заявлением
<?php
// Подключение к MySQL
$servername = "localhost"; // локалхост
$username = "root"; // имя пользователя
$password = ""; // пароль если существует
$dbname = "myDB"; // база данных
// Создание соединения
$conn = new mysqli($servername, $username, $password, $dbname);
// Проверка соединения
if ($conn->connect_error) {
die("Подключение не удалось: " . $conn->connect_error);
}
// Подготовить и связать
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// Установить параметры и выполнить
$firstname = "Федор";
$lastname = "Петров";
$email = "fed@example.ru";
$stmt->execute();
$firstname = "Петр";
$lastname = "Громыхалов";
$email = "petr@example.ru";
$stmt->execute();
$firstname = "Лева";
$lastname = "Быков";
$email = "leva@example.ru";
$stmt->execute();
echo "Успешно созданы новые записи";
// Закрыть связь
$stmt->close();
// Закрыть подключение
$conn->close();
?>
Объяснение примера:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
В SQL вставляем вопросительный знак (?
), где мы можем заменить integer, string, double или BLOB значение.
Затем посмотрите на функцию bind_param()
:
$stmt->bind_param("sss", $firstname, $lastname, $email);
Функция связывает параметры к SQL запросу и сообщает базе данных, параметры.
Аргумент "sss" перечисляет типы данных, которые являются параметрами.
Символ s
сообщает MySQL, что параметр является строкой.
Аргумент может быть одним из четырех типов:
- i - integer (целое число)
- d - double (двойной)
- s - string (строка)
- b - BLOB (большой двоичный объект)
Должен быть один из параметров.
Рассказывая о MySQL, какой тип данных следует ожидать, мы сводим к минимуму риск SQL инъекции.
Примечание: Если вставить какие-либо данные из внешних источников (например, данные пользователя), и очень важно, чтобы данные были очищены и проверены.
PDO Подготовленные заявления
В следующем примере используются подготовленные инструкции и связанные параметры в PDO:
Пример PDO (с подготовленными заявлениями)
<?php
$servername = "localhost"; // локалхост
$username = "root"; // имя пользователя
$password = ""; // пароль если существует
$dbname = "myDBPDO"; // база данных
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// Установить режим ошибки PDO в исключение
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Подготовить SQL и параметры привязки
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->bindParam(':email', $email);
// Вставить строку
$firstname = "Федор";
$lastname = "Петров";
$email = "fed@example.ru";
$stmt->execute();
// Вставить другую строку
$firstname = "Петр";
$lastname = "Громыхалов";
$email = "petr@example.ru";
$stmt->execute();
// Вставить еще одну строку
$firstname = "Лева";
$lastname = "Быков";
$email = "leva@example.ru";
$stmt->execute();
echo "Успешно созданы новые записи";
}
catch(PDOException $e)
{
echo "Ошибка: " . $e->getMessage();
}
// Закрыть подключение
$conn = null;
?>