Рассмотрим теперь подготовленные запросы PDO и то, как эффективно их использовать.
Подготовленный запрос - это шаблон для выполнения одного или нескольких SQL-запросов с различными значениями. Подготовленный оператор является высокоэффективным и помогает защитить приложение от SQL-инъекций.
Когда сервер базы данных выполняет запрос, он проходит два основных этапа: подготовка и выполнение.
Подготовка - сервер базы данных проверяет синтаксис SQL-запроса и инициализирует внутренние ресурсы сервера для этапа выполнения.
Выполнение - приложение связывает значения и отправляет SQL-запрос на сервер базы данных. Сервер базы данных выполняет запрос с привязанными значениями, используя внутренние ресурсы сервера, выделенные на этапе подготовки.
Содержание
Создание подготовленного запроса в PDO
Чтобы создать подготовленный запрос в PDO, выполните действия, которые я опишу ниже.
1. Во-первых, создаем шаблонный SQL-запрос. Например:
$sql = 'INSERT INTO authors (first_name, last_name)
VALUES (?, ?)';
В этом выражении INSERT
есть два вопросительных знака (?). Они называются позиционными заполнителями.
При выполнении оператора необходимо передать значения в позиционные заполнители по их позициям. Другими словами, например, в первый заполнитель нужно передать имя, а во второй - фамилию.
2. Во-вторых, вызовите метод prepare()
экземпляра PDO:
$statement = $pdo->prepare($sql);
Метод prepare()
возвращает новый экземпляр класса PDOStatement.
3. В-третьих, вызовите метод execute()
и передайте значения заполнителям:
$statement->execute(['Sandra', 'Aamodt']);
Метод execute()
заменит первый заполнитель на 'Sandra', а второй - на 'Aamodt' в операторе вставки.
Соединим все вместе.
Ниже показано, как использовать подготовленный запрос для вставки новой строки в таблицу "авторов":
<?php
$pdo = require 'connect.php';
$sql = 'insert into authors(first_name, last_name)
values(?,?)';
$statement = $pdo->prepare($sql);
$statement->execute(['Sandra', 'Aamodt']);
Выше в коде мы использовали вставку файла с данными для соединения с Базой Данных, как в статье PDO: cоединение с Базой Данных.
Использование именованных заполнителей
Когда вы используете позиционные заполнители в операторе SQL, вам необходимо передать значения, соответствующие позициям заполнителей.
Если в SQL-операторе много заполнителей, очень легко использовать неправильные позиции. Чтобы избежать этого, можно использовать именованные заполнители. Например:
$sql = 'INSERT INTO authors (first_name, last_name)
VALUES (:first_name,:last_name)';
В этом примере вместо вопросительных знаков (?) используется имя параметра, перед которым ставится двоеточие (:). Двоеточие требуется в операторе SQL.
При выполнении оператора необходимо передать ассоциативный массив в метод execute() следующим образом:
$statement->execute([
'first_name' => 'Henry',
'last_name' => 'Aaron'
]);
Обратите внимание, что важен ключ массива, а не порядок элементов. Также, можно использовать символ : в ключах массива по желанию:
$statement->execute([
':first_name' => 'Henry',
':last_name' => 'Aaron'
]);
Порядок элементов массива не важен, поэтому вы можете использовать массив с элементами в любом порядке. Например:
$statement->execute([
'last_name' => 'Aaron',
'first_name' => 'Henry',
]);
Соединим все вместе.
<?php
$pdo = require 'connect.php';
$sql = 'INSERT INTO authors (first_name, last_name)
VALUES (:first_name,:last_name)';
$statement = $pdo->prepare($sql);
$statement->execute([
'last_name' => 'Aaron',
'first_name' => 'Henry',
]);
Связанные значения
В приведенных выше примерах мы передаем значения в метод execute()
для выполнения запроса. Эти утверждения называются не связанными запросами.
Помимо несвязанных запросов, PDO также поддерживает связанные запросы. Связанные запросы позволяют явно связать значение или переменную с именованным или позиционным заполнителем.
Чтобы связать значение, используется метод bindValue()
объекта PDOStatement
:
public PDOStatement::bindValue ( mixed $parameter , mixed $value , int $data_type = PDO::PARAM_STR ) : bool
Метод bindValue()
имеет три параметра:
$parameter
задает имя параметра:parameter
, если в запросе используются именованные заполнители, или индекс параметра, если в запросе используются позиционные заполнители. В случае использования позиционных заполнителей первый параметр начинается с индекса 1.$value
указывает значение, которое нужно привязать к запросу.$data_type
указывает тип данных для параметра, используяPDO::PARAM_*
, например,PDO::PARAM_INT
. По умолчанию$data_type
- этоPDO::PARAM_STR
.
В следующем примере показано, как вставить автора Nick Abadzis
в таблицу authors
с помощью связанного запроса:
<?php
$pdo = require 'connect.php';
$sql = 'INSERT INTO authors (first_name, last_name)
VALUES (?, ?)';
$statement = $pdo->prepare($sql);
$statement->bindValue(':first_name', 'Nick');
$statement->bindValue(':last_name', 'Abadzis');
$statement->execute();
Когда вы используете метод bindValue()
, метод execute()
выполняет запрос со значениями, переданными методу bindValue()
, а не со значениями на момент выполнения метода execute()
. Например:
<?php
$pdo = require 'connect.php';
$sql = 'INSERT INTO authors (first_name, last_name)
VALUES (:first_name,:last_name)';
$statement = $pdo->prepare($sql);
$author = [
'first_name' => 'Chris',
'last_name' => 'Abani',
];
$statement->bindValue(':first_name', $author['first_name']);
$statement->bindValue(':last_name', $author['last_name']);
// изменение автора
$author['first_name'] = 'Tom';
$author['last_name'] = 'Abate';
// выполнение запроса со значением Chris Abani
$statement->execute();
В данном примере:
- Во-первых, привязываем значения 'Chris' и 'Abate' к параметрам имени и фамилии.
- Во-вторых, изменяем значения переменной
$author.
- В-третьих, выполняем запрос. Однако метод
execute()
использует значения, переданные методуbindValue()
, а не значение$author
на момент выполнения методаexecute()
.
Поэтому в дело вступает метод bindParam()
.
Метод bindParam()
Для выполнения запроса, значения параметров которого оцениваются во время выполнения метода execute(), используется метод bindParam()
:
public PDOStatement::bindParam ( mixed $parameter , mixed &$variable , int $data_type = PDO::PARAM_STR , int $length = ? , mixed $driver_options = ? ) : bool
Следующий пример иллюстрирует использование метода bindParam()
для вставки нового автора в таблицу authors
:
<?php
$pdo = require 'connect.php';
$sql = 'insert into authors(first_name, last_name)
values(:first_name,:last_name)';
$statement = $pdo->prepare($sql);
$author = [
'first_name' => 'Chris',
'last_name' => 'Abani',
];
$statement->bindParam(':first_name', $author['first_name']);
$statement->bindParam(':last_name', $author['last_name']);
// изменение переменной автора
$author['first_name'] = 'Tom';
$author['last_name'] = 'Abate';
// выполняем запрос со значением Tom Abate
$statement->execute();
В этом примере метод execute()
оценивает переменную $author
во время выполнения, поэтому вместо нее используются значения 'Tom' и 'Abage'.
Используйте подготовленный запрос PHP для многократного выполнения запроса с разными значениями.
Используйте позиционные заполнители (?) или именованные заполнители (:parameter
) в SQL-запросе, прежде чем передать его в метод prepare()
объекта PDOStatement
.
Используйте метод execute()
со значениями для запуска несвязанного запроса.
Используйте метод bindValue()
или bindParam()
для привязки значений к связанному запросу.