PHP MySQL Database

Prepared statements - Підготовлені вирази

Матеріал представлений на сторінці є моїм перекладом ресурсу w3schools.com/php/php_ref_mysqli.asp

PHP MySQL Database

Підготовлені вирази (Prepared Statements) ефективні проти SQL-ін'єкцій.

Prepared statements - Підготовлені Вирази та обмеження параметрів

Підготовлені Вирази (Prepared Statements) характерно з великою ефективністю виконують одинакові (схожі) SQL-запити.


Підготовлені Вирази в основному працюють таким чином:
1. Підготовка: Створюється та відправляється до СКБД шаблон SQL-запиту з значеннями, що не визначені (відмічені "?").
Наприклад,

INSERT INTO MyGuests VALUES(?, ?, ?)

2. Система керування Базою Даних парсить(аналізує), компілює та виконує оптимізацію шаблону SQL-запиту та зберігає результати без їхнього виконанння.

3. Виконання: Пізніше, програма отримує значення параметрів і СКБД виконує запит. Програма може виконувати запит стільки раз, скільки це необхідно для різних значень даних.


Порівнюючи пряме виконання SQL-запиту Підготовлений Вираз має дві основні переваги:
- Підготовлений Вираз знижує час парсингу(аналізу), так як підготовка запиту виконана лише один раз (хоча запит виконується декілька раз).
- Зв'язані параметри зменшують навантаження на сервер, поскільки Вам потрібно відправляти кожен раз лише параметри, а не весь запит.
- Підготовлений Вираз буде ефективним проти SQL-ін'єкцій, тому що значення параметрів, що будуть пізніше передаватись використовують різний протокол передачі даних.

Якщо шаблон SQL-виразу не побудований, застосовуючи зовнішнє введення даних, то виключається імовірність SQL-ін'єкції.

Підготовлений Вираз та MySQLi

    Слідуючий приклад використовує Підготовлений Вираз та обмежує параметри в MySQLi.

<?php
$servername = "localhost";
$username = "username";
$password = "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 = "John";
$lastname = "Doe";
$email = "john@example.com";
$stmt->execute();

$firstname = "Mary";
$lastname = "Moe";
$email = "mary@example.com";
$stmt->execute();

$firstname = "Julie";
$lastname = "Dooley";
$email = "julie@example.com";
$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-ін'єкцій.

info label

Якщо нам необхідно внести любі дані із зовнішнього джерела даних ( наприклад, дані, що вносить користувач), дуже важливо, щоб дані перевірялись та проходили перевірку на коректність та правильність вводу.



Підготовлені Вирази та PDO стиль кодування



<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";

try {
       $conn = new PDO("mysql:host=$servername; dbname=myDB", $username, $password);

       // встановлення PDO на випадок помилки з'єднання ( exception )
       $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 = "John";
       $lastname = "Doe";
       $email = "john@example.com";
       $stmt->execute();

       // встановлюємо ще один рядок
       $firstname = "Mary";
       $lastname = "Moe";
       $email = "mary@example.com";
       $stmt->execute();

       // встановлюємо ще один рядок
       $firstname = "Julie";
       $lastname = "Dooley";
       $email = "julie@example.com";
       $stmt->execute();

       echo "Нові записи успішно добавлені";
       }

catch(PDOException $e)
       {
       echo " Помилка " . $e->getMessage();
       }

$conn = null;
?>