Подготовленные операторы PHP MySQL
Подготовленные операторы очень полезны против SQL-инъекций.
Подготовленные операторы и связанные параметры
Подготовленный оператор — это функция, используемая для повторного выполнения одних и тех же (или похожих) операторов SQL с высокой эффективностью.
Подготовленные операторы в основном работают следующим образом:
- Подготовка: шаблон оператора SQL создается и отправляется в базу данных. Некоторые значения остаются неуказанными, называемыми параметрами (помечены «?»). Пример: INSERT INTO MyGuests VALUES(?, ?, ?)
- База данных анализирует, компилирует и выполняет оптимизацию запроса по шаблону оператора SQL и сохраняет результат без его выполнения.
- Выполнение: позже приложение привязывает значения к параметрам, и база данных выполняет оператор. Приложение может выполнять оператор сколько угодно раз с разными значениями.
По сравнению с непосредственным выполнением операторов SQL подготовленные операторы имеют три основных преимущества:
- Подготовленные операторы сокращают время анализа, поскольку подготовка запроса выполняется только один раз (хотя оператор выполняется несколько раз).
- Связанные параметры минимизируют пропускную способность сервера, так как вам нужно каждый раз отправлять только параметры, а не весь запрос
- Подготовленные операторы очень полезны против SQL-инъекций, потому что значения параметров, которые передаются позже с использованием другого протокола, не нуждаются в правильном экранировании. Если исходный шаблон оператора не является производным от внешнего ввода, внедрение SQL невозможно.
Подготовленные операторы в MySQLi
В следующем примере используются подготовленные операторы и связанные параметры в MySQLi:
Пример (MySQLi с подготовленными операторами)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
$stmt->close();
$conn->close();
?>
Строки кода для объяснения из приведенного выше примера:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
В нашем SQL мы вставляем вопросительный знак (?) Там, где мы хотим заменить целое число, строку, двойное значение или значение blob.
Затем взгляните на функцию bind_param():
$stmt->bind_param("sss", $firstname, $lastname, $email);
Эта функция связывает параметры с SQL-запросом и сообщает базе данных, что это за параметры. Аргумент "sss" перечисляет типы данных, которыми являются параметры. Символ s сообщает mysql, что параметр является строкой.
Аргумент может быть одного из четырех типов:
- я - целое число
- д - двойной
- с - строка
- б - BLOB
Мы должны иметь один из них для каждого параметра.
Сообщая mysql, какой тип данных ожидать, мы минимизируем риск SQL-инъекций.
Примечание. Если мы хотим вставить какие-либо данные из внешних источников (например, пользовательский ввод), очень важно, чтобы данные были очищены и проверены.
Подготовленные заявления в PDO
В следующем примере используются подготовленные операторы и связанные параметры в PDO:
Пример (PDO с подготовленными операторами)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare sql and bind parameters
$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);
// insert a row
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
} catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>