Подготовленные запросы

Подготовленные запросы




Неименованный плейсхолдер

Метод prepare()

Метод execute()

Именованный плейсхолдер

Связывание параметра запроса с некой переменной

Метод bindParam()




Подготовленные запросы рекомендуется использовать вместо обычных запросов, потому что подготовленный запрос - это уже готовое, скомпилированное выражение к которому можно обращаться многократно просто передавая необходимые параметры.

Эти запросы работают намного быстрее и намного безопаснее, особенно, если в запросах используются условия с передаваемыми параметрами.

То есть, подготовленные запросы обеспечивают очень высокую безопасность от sql-инъекций.




Запрос на выборку данных:


Выбрать все из таблицы news, где id = 2.

Обычно параметр id передается из вне, поэтому создадим переменную $id и в ней будем хранить передаваемые данные (в данном случае - 2).

Данный параметр мы получаем, например, из формы: формы авторизации, формы регистрации и т.д.

И, соответственно, этот параметр попадет в запрос (id = '$id').

С помощью стандартного метода query() выполняем запрос и распечатываем его на экран, используя метод fetchAll().


$id = 2;
$sql = "SELECT id, title FROM news WHERE id = '$id'";
$result = $pdo -> query($sql);
print_r($result -> fetchAll(PDO::FETCH_ASSOC));
После выполнения запроса получим:
Успешное подключение
Array ( [0] => Array ( [id] => 2 [title] => Новость 2 ) )


- все успешно работает, но данный код не безопасен.


Чтобы обеспечить безопасность от sql-инъекций будем использовать подготовленное выражение.



Неименованный плейсхолдер


Определив некий sql-запрос, в качестве параметра указываем метку - ? (вопросительный знак) - так называемый неименованный плэйсхолдер (placeholder - заполнитель).

Этим мы как бы указываем, что здесь должен быть указан некий параметр.

Затем данное выражение мы должны подготовить с помощью метода prepare() - то есть, указываем объекту PDO, что необходимо подготовить данное выражение.

Данный запрос будет скомпилирован, подготовлен и будет ждать своего выполнения

Далее, при необходимости, мы можем выполнять некий код, а в конце скрипта мы можем выполнить данный запрос.

Чтобы выполнить запрос обращаемся к объекту PDOStatement ($result) и вызываем на исполнение метод execute()

Метод execute() - выполняет подготовленное выражение.

В качестве параметра метода execute() передаем массив:

- в качестве первой ячейки мы используем переменную, которую заменил плэйсхолдер, в нашем случае - $id .


$id = 2;
$sql = "SELECT id, title FROM news WHERE id = ?";
$result = $pdo -> prepare($sql);
// При необходимости, здесь мы можем выполнять некий код ...
$result->execute(array($id));
print_r($result -> fetchAll(PDO::FETCH_ASSOC));
После выполнения запроса получим:
Успешное подключение
Array ( [0] => Array ( [id] => 2 [title] => Новость 2 ) )


- после выполнения запроса в браузере ни чего не изменилось.

Данный запрос уже безопасен и ему не страшны sql-инъекции.



Именованный плейсхолдер


Вместо неименованных плейсхолдеров (?) можно использовать именованные плейсхолдеры (например, для нашего случая - :id) - то есть, мы явно указываем имя данного параметра.

А это значит, что при вызове метода execute(), в качестве параметра, мы уже передаем ассоциативный массив.

В качестве ячейки которого указываем ключ 'id', а в качестве значения данной ячейки указываем параметр $id:


........
$sql = "SELECT id, title FROM news WHERE id = :id";
........
$result->execute(array('id' => $id));
или (альтернативная запись для массива):
$result->execute(['id' => $id]);
........



Связывание параметра запроса с некой переменной.

Метод bindParam()


Метод bindParam() привязывает параметр запроса (плэйсхолдер) к определенной переменной.

Первым параметром он принимает имя плэйсхолдера (':id'), а в качестве второго параметра - переменную ($id), к значению которой (2) будет привязан данный плэйсхолдер.

В качестве третьего параметра указываем тип данных, который будет передаваться в данный плэйсхолдер, в нашем случае - PDO::PARAM_INT (целочисленный тип данных).


...........
$result->bindParam(':id', $id, PDO::PARAM_INT);
$result->execute();
...........




Файл index.php


-- файл index.php --

<?php

try{
$pdo = new PDO ('mysql:host=localhost;dbname=test2';charset=utf-8, 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Успешное подключение <br><br>";
} catch{
exit ('Ошибка подключения: <br><br>' . $e -> getMessage());
}

try{

------- Без использования плэйсхолдера ---------

$id = 2;
$sql = "SELECT id, title FROM news WHERE id = '$id'";
$result = $pdo -> query($sql);
print_r($result -> fetchAll(PDO::FETCH_ASSOC));

------- Неименованный плейсхолдер ----------------

$id = 2;
$sql = "SELECT id, title FROM news WHERE id = ?";
$result = $pdo -> prepare($sql);
// При необходимости, здесь мы можем выполнять некий код ...
$result->execute(array($id));
print_r($result -> fetchAll(PDO::FETCH_ASSOC));

-------- Именованный плейсхолдер --------------------

$id = 2;
$sql = "SELECT id, title FROM news WHERE id = :id";
$result = $pdo -> prepare($sql);
// При необходимости, здесь мы можем выполнять некий код ...
$result->execute(array('id' => $id));
print_r($result -> fetchAll(PDO::FETCH_ASSOC));

------------ Использование метода bindParam()----------------------

$id = 2;
$sql = "SELECT id, title FROM news WHERE id = :id";
$result = $pdo -> prepare($sql);
// При необходимости, здесь мы можем выполнять некий код ...

$result->bindParam(':id', $id, PDO::PARAM_INT);
$result->execute();

print_r($result -> fetchAll(PDO::FETCH_ASSOC));

------------------------------------------------------------

} catch{
exit ('Ошибка в запросе: <br><br>' . $e -> getMessage());
}
?>

Во всех случаях получим:
Успешное подключение
Array ( [0] => Array ( [id] => 2 [title] => Новость 2 ) )






Наверх Наверх