Webzone Публикации PHP PHP - База данных MySQL PDO

PHP - База данных MySQL PDO

14:58 , 08 Август 2019
PHP - База данных MySQL PDO

PDO (PHP Data Objects) — расширение PHP, которое реализует взаимодействие с базами данных при помощи объектов. Профит в том, что отсутствует привязка к конкретной системе управления базами данных. PDO поддерживает СУБД: MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server и другие.

Функции mysql в PHP для работы с БД давно уже устарели, на сегодняшний день желательно использовать mysqli или PDO (PHP Data Objects). Кроме того, mysqli - эта библиотека, которая по большому счёту, не предназначена для использования напрямую в коде. Она может послужить хорошим строительным материалом для создания библиотеки более высокого уровня. При работе с mysqli следует также помнить об обеспечении безопасности вашего приложения, в частности о защите от SQL-инъекций. В случае использования PDO (с его подготовленными запросами), такая защита идёт уже "из коробки", главное правильно применить необходимые методы.



Установка PDO


// Установка в Linux
sudo apt update
sudo apt install php7.2-mysql
sudo apt-get install pdo-mysql
 
// В php.ini добавить
extension=pdo.so
extension=pdo_mysql.so
 
// На Windows, как правило драйвер уже установлен, нужно просто проверить включен ли он в php.ini
extension=php_pdo_mysql.dll




Соединение с базой данных

Соединения устанавливаются автоматически при создании объекта PDO от его базового класса.


$db = new PDO('mysql:host=localhost;dbname=pdo', 'root', 'password');




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

В PDO два способа выполнения запросов:
1. Прямой - состоит из одного шага;
Подготовленный - состоит из двух шагов.

Прямые запросы
- query() используется для операторов, которые не вносят изменения, например SELECT. Возвращает объект PDOStatemnt, из которого с помощью методов fetch() или fetchAll извлекаются результаты запроса. Можно его сравнить с mysql resource, который возвращала mysql_query().
- exec() используется для операторов INSERT, DELETE, UPDATE. Возвращает число обработанных запросом строк.

Прямые запросы используются только в том случае, если в запросе отсутствуют переменные и есть уверенность, что запрос безопасен и правильно экранирован.



$stmt = $db->query("SELECT * FROM categories");
while ($row = $stmt->fetch())
{
  echo '<pre>';
  print_r($row);
}




Подготовленные запросы
Если же в запрос передаётся хотя бы одна переменная, то этот запрос в обязательном порядке должен выполняться только через подготовленные выражения. Что это значит? Это обычный SQL запрос, в котором вместо переменной ставится специальный маркер - плейсхолдер. PDO поддерживает позиционные плейсхолдеры (?), для которых важен порядок передаваемых переменных, и именованные (:name), для которых порядок не важен. Примеры:


$sql = "SELECT name FROM categories WHERE id = ?";
$sql = "SELECT name FROM categories WHERE name = :name";



Чтобы выполнить такой запрос, сначала его надо подготовить с помощью метода prepare(). Она также возвращает PDO statement, но ещё без данных. Чтобы их получить, надо исполнить этот запрос, предварительно передав в него наши переменные. Передать можно двумя способами: Чаще всего можно просто выполнить метод execute(), передав ему массив с переменными:


$stmt = $pdo->prepare("SELECT `name` FROM categories WHERE `id` = ?");
$stmt->execute([$id]);
 
$stmt = $pdo->prepare("SELECT `name` FROM categories WHERE `name` = :name");
$stmt->execute(['name' => $name]);



Как видно, в случае именованных плейсхолдеров в execute() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров. После этого можно извлечь результаты запроса:


$stmt = $pdo->prepare("SELECT `name` FROM categories WHERE `id` = ?");
$stmt->execute([$id]);
 
$stmt = $pdo->prepare("SELECT `name` FROM categories WHERE `name` = :name");
$stmt->execute(['name' => $name]);




Получение данных. Метод fetch()

Мы уже выше познакомились с методом fetch(), который служит для последовательного получения строк из БД. Этот метод является аналогом функции mysq_fetch_array() и ей подобных, но действует по-другому: вместо множества функций здесь используется одна, но ее поведение задается переданным параметром. В подробностях об этих параметрах будет написано в другой заметке , а в качестве краткой рекомендации посоветую применять fetch() в режиме FETCH_LAZY



$id = 1;
$stmt = $db->prepare("SELECT * FROM categories WHERE `id` = ?");
$stmt->execute([$id]);
while ($row = $stmt->fetch(PDO::FETCH_LAZY)) {
    echo 'Category name: '.$row->name;
}


В этом режиме не тратится лишняя память, и к тому же к колонкам можно обращаться любым из трех способов - через индекс, имя, или свойство (через ->). Недостатком же данного режима является то, что он не работает с fetchAll()



Получение данных. Метод fetchAll()


$data = $db->query("SELECT * FROM categories")->fetchAll(PDO::FETCH_ASSOC);
foreach ($data as $k => $v){
  echo 'Category name: '.$v['name'].'
'; }


PDO и оператор LIKE

Работая с подготовленными запросами, следует понимать, что плейсхолдер может заменять только строку или число. Ни ключевое слово, ни идентификатор, ни часть строки или набор строк через плейсхолдер подставить нельзя. Поэтому для LIKE необходимо сначала подготовить строку поиска целиком, а потом ее подставлять в запрос:


$search = 'комп';
$query = "SELECT * FROM categories WHERE `name` LIKE ?";
$params = ["%$search%"];
$stmt = $db->prepare($query);
$stmt->execute($params);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
$i = 1;
foreach ($data as $category){
  echo $i++ . '. ' . $category['name'].'
'; }


Добавление записей


$name = 'Новая категория';
$query = "INSERT INTO `categories` (`name`) VALUES (:name)";
$params = [
    ':name' => $name
];
$stmt = $pdo->prepare($query);
$stmt->execute($params);




Изменение записей


$id = 1;
$name = 'Изменённая запись';
$query = "UPDATE `categories` SET `name` = :name WHERE `id` = :id";
$params = [
    ':id' => $id,
    ':name' => $name
];
$stmt = $pdo->prepare($query);
$stmt->execute($params);




Удаление записей


$id = 1;
$query = "DELETE FROM `categories` WHERE `id` = ?";
$params = [$id];
$stmt = $pdo->prepare($query);
$stmt->execute($params);




Использование транзакций


try {
  // Начало транзакции
  $pdo->beginTransaction();
  // ... code
  // Если в результате выполнения нашего кода всё прошло успешно,
  // то зафиксируем этот результат
  $pdo->commit();
} catch (Exception $e) {
  // Иначе, откатим транзакцию. 
  $pdo->rollBack();
  echo "Ошибка: " . $e->getMessage();
}




В данной публикации мы познакомились с основными понятиями PDO, его установкой, подключением к БД и самые простые возможности выборки, изменения и удаления данных. В следующих публикациях мы рассмотрим ещё несколько тем, касающихся PDO.



Вопросы / Комментарии / Отзывы