Php mysql pdo try catch

Ошибки и их обработка

PDO предлагает на выбор 3 стратегии обработки ошибок в зависимости от вашего стиля разработки приложений.

  • PDO::ERRMODE_SILENT Это режим по умолчанию. PDO просто предоставит вам код ошибки, который можно получить методами PDO::errorCode() и PDO::errorInfo() . Эти методы реализованы как в объектах запросов так и в объектах баз данных. Если ошибка вызвана во время выполнения кода объекта запроса, нужно вызвать метод PDOStatement::errorCode() или PDOStatement::errorInfo() этого объекта. Если ошибка вызова объекта базы данных, нужно вызвать аналогичные методы у этого объекта.
  • PDO::ERRMODE_WARNING Помимо задания кода ошибки PDO выдаст обычное E_WARNING сообщение. Это может быть полезно при отладке или тестировании, когда нужно видеть, что произошло, но не нужно прерывать работу приложения.
  • PDO::ERRMODE_EXCEPTION Помимо задания кода ошибки PDO будет выбрасывать исключение PDOException, свойства которого будут отражать код ошибки и ее описание. Этот режим также полезен при отладке, так как сразу известно, где в программе произошла ошибка. Это позволяет быстро локализовать и решить проблему. (Не забывайте, что если исключение является причиной завершения работы скрипта, все активные транзакции будут откачены.) Режим исключений также полезен, так как дает возможность структурировать обработку ошибок более тщательно, нежели с обычными PHP предупреждениями, а также с меньшей вложенностью кода, чем в случае работы в тихом режиме с явной проверкой возвращаемых значений при каждом обращении к базе данных. Подробнее об исключениях в PHP см. в разделе Исключения.
Читайте также:  Java collection contains object

PDO стандартизирован для работы со строковыми кодами ошибок SQL-92 SQLSTATE. Отдельные PDO драйверы могут задавать соответствия своих собственных кодов кодам SQLSTATE. Метод PDO::errorCode() возвращает одиночный SQLSTATE код. Если необходима специфичная информация об ошибке, PDO предлагает метод PDO::errorInfo() , который возвращает массив, содержащий SQLSTATE код, код ошибки драйвера, а также строку ошибки драйвера.

Пример #1 Создание PDO объекта и задание режима обработки ошибок

$dsn = ‘mysql:dbname=testdb;host=127.0.0.1’ ;
$user = ‘dbuser’ ;
$password = ‘dbpass’ ;

try $dbh = new PDO ( $dsn , $user , $password );
$dbh -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );
> catch ( PDOException $e ) echo ‘Подключение не удалось: ‘ . $e -> getMessage ();
>

Замечание:

Метод PDO::__construct() будет всегда бросать исключение PDOException, если соединение оборвалось, независимо от установленного значения PDO::ATTR_ERRMODE . Непойманные исключения фатальны.

Пример #2 Создание экземпляра класса PDO и задание режима обработки ошибок в конструкторе

$dsn = ‘mysql:dbname=test;host=127.0.0.1’ ;
$user = ‘googleguy’ ;
$password = ‘googleguy’ ;

/*
По прежнему оберните конструктор в блок try/catch, так как, даже при установке ERRMODE в WARNING,
PDO::__construct всегда будет бросать исключение PDOException, если соединение оборвалось.
*/
try $dbh = new PDO ( $dsn , $user , $password , array( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_WARNING ));
> catch ( PDOException $e ) echo ‘Соединение оборвалось: ‘ . $e -> getMessage ();
exit;
>

// Следующий запрос приводит к ошибке уровня E_WARNING вместо исключения (когда таблица не существует)
$dbh -> query ( «SELECT wrongcolumn FROM wrongtable» );
?>

Результат выполнения данного примера:

Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.wrongtable' doesn't exist in /tmp/pdo_test.php on line 18

Источник

PHP: PDO быстрый старт, работа с MySQL

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

Официальный мануал по PHP PDO здесь . Там же можно найти и сам класс PDO .

Почему стоит использовать PDO

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

Тестовая база данных с таблицей

// Из консоли Windows mysql> CREATE DATABASE `pdo-test` CHARACTER SET utf8 COLLATE utf8_general_ci; USE pdo-test; CREATE TABLE categories ( id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), name VARCHAR(255) NOT NULL ); INSERT INTO `categories` (`name`) VALUES ('Ноутбуки и планшеты'), ('Компьютеры и периферия'), ('Комплектующие для ПК'), ('Смартфоны и смарт-часы'), ('Телевизоры и медиа'), ('Игры и приставки'), ('Аудиотехника'), ('Фото-видеоаппаратура'), ('Офисная техника и мебель'), ('Сетевое оборудование'), ('Крупная бытовая техника'), ('Товары для кухни'), ('Красота и здоровье'), ('Товары для дома'), ('Инструменты'), ('Автотовары');

Установка PDO

// Установка в Linux sudo apt update sudo apt install php8.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

Проверить доступные драйвера

print_r(PDO::getAvailableDrivers());

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

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

// Пример #1. Простое подключение $db = new PDO('mysql:host=localhost;dbname=pdo', 'root', 'password');

При ошибке подключения PHP выдаст ошибку:

Fatal error: Uncaught PDOException: . 
// Пример #2. Обработка ошибок подключения try < $dbh = new PDO('mysql:host=localhost;dbname=pdo', 'root', 'password'); >catch (PDOException $e) < print "Error!: " . $e->getMessage(); die(); >

В этом примере подключения мы используем конструкцию try. catch . Многие спорят о целесообразности её использования. Лично я использую try. catch , она мне не мешает.

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

В PDO два способа выполнения запросов:

Прямые запросы

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

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

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

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

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

$sql = "SELECT name FROM categories WHERE = "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() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров. После этого можно извлечь результаты запроса:

$id = 1; $stmt = $db->prepare("SELECT * FROM categories WHERE `id` = ?"); $stmt->execute([$id]); $category = $stmt->fetch(PDO::FETCH_LAZY); echo '
'; print_r($category);

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

Получение данных. Метод 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()

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

Также у PDO statement есть метод для получения значения единственной колонки. Очень удобно, если мы запрашиваем только одно поле - в этом случае значительно сокращается количество кода:

$id = 1; $stmt = $db->prepare("SELECT `name` FROM categories WHERE `id` = ?"); $stmt->execute([$id]); $name = $stmt->fetchColumn(); echo 'Category name: '.$name;

Получение данных. Метод 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'].'
'; >

Здесь может вознинуть проблема! Поиск может не работать, потому как из базы у вас приходят данные в неправильной кодировке. Необходимо добавить кодировку в подключение, если она там не указана!

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

PDO и оператор LIMIT

Важно! Когда PDO работает в режиме эмуляции, все данные, которые были переданы напрямую в execute() , форматируются как строки. То есть, эскейпятся и обрамляются кавычками. Поэтому LIMIT . превращается в LIMIT '10', '10' и очевидным образом вызывает ошибку синтаксиса и, соответственно, пустой массив данных.

Решение #1 : Отключить режим эмуляции:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Решение #2 : Биндить эти цифры через bindValue() , принудительно выставляя им тип PDO::PARAM_INT :

$limit = 3; $stm = $db->prepare('SELECT * FROM categories LIMIT ?'); $stm->bindValue(1, $limit, PDO::PARAM_INT); $stm->execute(); $data = $stm->fetchAll(); echo '
'; print_r($data);

PDO и оператор IN

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

$arr = [1,3,6]; $in = str_repeat('?,', count($arr) - 1) . '?'; $sql = "SELECT * FROM categories WHERE `id` IN ($in)"; $stm = $db->prepare($sql); $stm->execute($arr); $data = $stm->fetchAll(); echo '
'; print_r($data);

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

$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, его установкой, подключением к БД и самые простые возможности выборки, изменения и удаления данных.

Источник

Оцените статью