Правилата за добавяне на PHP променлива във всеки MySQL израз са ясни и прости:
- Всяка променлива, която представлява SQL литерал от данни , (или, по-просто казано - SQL низ, или число) ТРЯБВА да се добави чрез подготвен оператор. Без изключения.
- Всяка друга част от заявката, като SQL ключова дума, таблица или име на поле, или оператор - трябва да се филтрира през бял списък .
Тъй като вашият пример включва само литерали от данни, тогава всички променливи трябва да бъдат добавени чрез заместители (наричани още параметри). За да направите това:
- В SQL израза заменете всички променливи с заместители
- подгответе се получената заявка
- свързване променливи към заместители
- изпълни заявката
И ето как да го направите с всички популярни драйвери за база данни на PHP:
Добавяне на литерали на данни чрез mysql ext
Такъв драйвер не съществува .
Добавяне на литерали от данни с помощта на mysqli
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();
Кодът е малко сложен, но подробното обяснение на всички тези оператори може да се намери в моята статия, Как да стартирам INSERT заявка с Mysqli , както и решение, което значително улеснява процеса.
За заявка SELECT ще трябва да добавите само извикване към get_result()
метод за получаване на познат mysqli_result
от който можете да извлечете данните по обичайния начин:
$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
Добавяне на литерали от данни чрез PDO
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);
В PDO можем да комбинираме частите за свързване и изпълнение, което е много удобно. PDO също поддържа именувани заместители, които някои намират за изключително удобни.
Добавяне на ключови думи или идентификатори
Понякога трябва да добавим променлива, която представлява друга част от заявка, като ключова дума или идентификатор (база данни, таблица или име на поле). Това е рядък случай, но е по-добре да сте подготвени.
В този случай вашата променлива трябва да бъде проверена спрямо списък със стойности изрично написано във вашия скрипт. Това е обяснено в другата ми статия, Добавяне на име на поле в клаузата ORDER BY въз основа на избора на потребителя :
За съжаление PDO няма заместител за идентификатори (имена на таблици и полета), поради което разработчикът трябва да ги филтрира ръчно. Такъв филтър често се нарича „бял списък“ (където изброяваме само разрешени стойности), за разлика от „черен списък“, където изброяваме забранени стойности.
Така че трябва изрично да изброим всички възможни варианти в PHP кода и след това да изберем от тях.
Ето един пример:
$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) {
throw new InvalidArgumentException("Invalid field name");
}
Точно същият подход трябва да се използва за посоката,
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
След такъв код и двете $direction
и $orderby
променливите могат безопасно да бъдат поставени в SQL заявката, тъй като те или са равни на един от разрешените варианти, или ще бъде изведена грешка.
Последното нещо, което трябва да споменем за идентификаторите, те също трябва да бъдат форматирани според конкретния синтаксис на базата данни. За MySQL трябва да е backtick
знаци около идентификатора. Така че последният низ на заявка за нашата поръчка чрез пример ще бъде
$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";