что такое pdo php
PDO в PHP
PDO (PHP Data Objects) — расширение для PHP, предоставляющее простой интерфейс для доступа к различным базам данных. Если говорить очень просто и коротко, при помощи PDO в PHP подключаются к базам данных разных типов.
В этом уроке мы будем подключаться к базе данных MySQL, так как это самая распространённая база данных.
Подключение к базе данных
Вы должны знать, что у сервера баз данных есть имя, также к нему могут подключаться пользователи, то есть для подключения должен быть использован логин и пароль.
Пример того, как мы можем подключиться к базе данных:
Я думаю если вы интересуетесь PDO, то ваших знаний достаточно и этот синтаксис вам объяснять не нужно.
Итак, у нас есть объект подключения для доступа к базе данных.
Обработка исключений
Когда используется PDO, то ошибки подключений советуюю ловить при помощи конструкции try<. >catch <. >. Вот пример такого кода:
Есть разные мнения, по поводу обработки ошибок, например не все советуют всегда использовать конструкцию try<. >catch <. >. Дело в том, что PHP и так выведет сообщение об ошибке на экран, так что этот код избыточен. Хотя если вы хотите например откатить транзакцию, то эта конструкция вам пригодится, но об этом ниже.
Получение данных из базы используя PDO, метод query
Не забывайте, что для всех типов баз данных этот синтаксис сработает.
Обработка результата, методы FETCH и FETCHALL.
Очевидно, что константа FETCH_LAZY замедляет работу скрипта, поэтому её желательно не использовать.
Константа FETCH_CLASS
Давайте рассмотрим пример, с использованием константы FETCH_CLASS :
Не забывайте важное правило — названия свойств в созданном классе обязаны быть такими же, как и названия полей в базе данных.
Подготовленные выражения
Подготовленные выражения нужно обязательно использовать если ваш SQL запрос содержит переменные.
Подготовленные выражения PDO — основная причина использовать PHP Data Objects, поскольку это единственный безопасный способ выполнения SQL запросов, в которых есть переменные, созданные пользователем.
Именнованные плейсхолдеры
Давайте рассмотрим пример запроса INSERT с использованием плейсхолдеров.
Итак, ещё раз последовательность работы с подготовленными выражениями по шагам:
Этот синтаксис можно записать
Видно, что в метод execute() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров.
Неименованные плейсхолдеры
Теперь рассмотрим работу с неименованными плейсхолдерами.
Вот другой пример применения неименованных плейсхолдеров, с использованием метода bindParam() :
Вставка в базу данных, метод exec()
Настройка и использование PDO — расширения PHP Data Objects для работы с базами данных
PDO (PHP Data Objects) — расширение PHP, которое реализует взаимодействие с базами данных при помощи объектов. Профит в том, что отсутствует привязка к конкретной системе управления базами данных.
Предоставляемый интерфейс поддерживает, среди прочих, такие популярные СУБД:
В этом руководстве представлен обзор PDO:
Для работы потребуются:
Создание тестовой базы данных и таблицы
Для начала создадим базу данных для этого руководства:
Теперь создадим таблицу и заполним данными, астрономическая точность которых не подразумевается:
Описание соединения
Теперь, когда создана база, определим DSN (Data Source Name) — сведения для подключения к базе, представленные в виде строки. Синтаксис описания отличается в зависимости от используемой СУБД. В примере работаем с MySQL/MariaDB, поэтому указываем:
Строка DSN в этом случае выглядит следующим образом:
Создание PDO-объекта
Теперь, когда строка DSN готова, создадим PDO-объект. Конструктор на входе принимает следующие параметры:
Дополнительные параметры можно также определить после создания объекта с помощью метода SetAttribute :
Определение метода выборки по умолчанию
PDO::DEFAULT_FETCH_MODE — важный параметр, который определяет метод выборки по умолчанию. Указанный метод используется при получении результата выполнения запроса.
PDO::FETCH_BOTH
Режим по умолчанию. Результат выборки индексируется как номерами (начиная с 0), так и именами столбцов:
После выполнения запроса с этим режимом к тестовой таблице планет получим следующий результат:
PDO::FETCH_ASSOC
Результат сохраняется в ассоциативном массиве, в котором ключ — имя столбца, а значение — соответствующее значение строки:
В результате получим:
PDO::FETCH_NUM
При использовании этого режима результат представляется в виде массива, индексированного номерами столбцов (начиная с 0):
PDO::FETCH_COLUMN
Этот вариант полезен, если нужно получить перечень значений одного поля в виде одномерного массива, нумерация которого начинается с 0. Например:
В результате получим:
PDO::FETCH_KEY_PAIR
Используем этот вариант, если нужно получить перечень значений двух полей в виде ассоциативного массива. Ключи массива — это данные первого столбца выборки, значения массива — данные второго столбца. Например:
В результате получим:
PDO::FETCH_OBJECT
При использовании PDO::FETCH_OBJECT для каждой извлеченной строки создаётся анонимный объект. Его общедоступные (public) свойства — имена столбцов выборки, а результаты запроса используются в качестве их значений:
В результате получим:
PDO::FETCH_CLASS
В этом случае, как и в предыдущем, значения столбцов становятся свойствами объекта. Однако требуется указать существующий класс, который будет использоваться для создания объекта. Рассмотрим это на примере. Для начала создадим класс:
Обратите внимание, что у класса Planet закрытые (private) свойства и нет конструктора. Теперь выполним запрос.
В результате получим объект Planet :
Значения, полученные в результате запроса, назначены соответствующим свойствам объекта, даже закрытым.
Определение свойств после выполнения конструктора
В классе Planet нет явного конструктора, поэтому проблем при назначении свойств не будет. При наличии у класса конструктора, в котором свойство было назначено или изменено, они будут перезаписаны.
При использовании константы FETCH_PROPS_LATE значения свойств будут присваиваться после выполнения конструктора:
В результате получим:
Как и ожидалось, извлеченные из базы данных значения перезаписаны. Теперь рассмотрим решение задачи с помощью FETCH_PROPS_LATE (запрос аналогичный):
В результате получим то, что нужно:
Если у конструктора класса нет значений по умолчанию, а они нужны, параметры конструктора задаются при вызове метода setFetchMode третьим аргументом в виде массива. Например:
Аргументы конструктора обязательны, поэтому выполним:
Входящие параметры выступают также в роли значений по умолчанию, которые нужны для инициализации. В дальнейшем они будут перезаписаны значениями из базы данных.
Получение нескольких объектов
Множественные результаты извлекаются в виде объектов с помощью метода fetch внутри цикла while :
PDO::FETCH_INTO
Подготовленные и прямые запросы
В PDO два способа выполнения запросов:
Прямые запросы
Существует два метода выполнения прямых запросов:
Прямые операторы используются только в том случае, если в запросе отсутствуют переменные и есть уверенность, что запрос безопасен и правильно экранирован.
Подготовленные запросы
PDO поддерживает подготовленные запросы (prepared statements), которые полезны для защиты приложения от SQL-инъекций: метод prepare выполняет необходимые экранирования.
Неименованные псевдопеременные
Именованные псевдопеременные
При использовании именованных псевдопеременных (named placeholders) порядок передачи значений для подстановки не важен, но код в этом случае становится не таким компактным. В метод execute данные передаются в виде ассоциативного массива, в котором каждый ключ соответствует имени псевдопеременной, а значение массива — значению, которое требуется подставить в запрос. Переделаем предыдущий пример:
Методы prepare и execute используются как при выполнении запросов на изменение, так и при выборке.
Управление поведением PDO при ошибках
PDO::ERRMODE_SILENT
Вариант по умолчанию. PDO просто запишет информацию об ошибке, которую помогут получить методы errorCode и errorInfo.
PDO::ERRMODE_EXCEPTION
Это предпочтительный вариант, при котором в дополнение к информации об ошибке PDO выбрасывает исключение (PDOException). Исключение прерывает выполнение скрипта, что полезно при использовании транзакций PDO. Пример приведён ниже при описании транзакций.
PDO::ERRMODE_WARNING
В этом случае PDO также записывает информацию об ошибке. Поток выполнения скрипта не прерывается, но выдаются предупреждения.
Методы bindValue и bindParam
Транзакции в PDO
Транзакции позволяют сохранить на некоторое время и организовать выполнение нескольких запросов «пакетом». Запросы, включённые в транзакцию, применяются только в том случае, если при выполнении отсутствуют ошибки. Транзакции поддерживаются не всеми СУБД и работают не со всеми SQL-конструкциями, так как некоторые из них вызывают неявное выполнение. Список таких конструкций можно найти на сайте MariaDB.
Представим необычный пример. Пользователю требуется выбрать список планет, причём каждый раз при выполнении запроса текущие данные удаляются из базы, а потом вставляются новые. Если после удаления произойдёт ошибка, то следующий пользователь получит пустой список. Чтобы этого избежать, используем транзакции:
Заключение
Теперь, когда работа с PDO описана, отметим его основные преимущества:
Хинт для программистов: если зарегистрируетесь на соревнования Huawei Cup, то бесплатно получите доступ к онлайн-школе для участников. Можно прокачаться по разным навыкам и выиграть призы в самом соревновании.
Перейти к регистрации
Как работать с PDO? Полное руководство.
По-хорошему, надо бы, конечно, завернуть все обращения к API в библиотеку, и пользоваться только ей. Но поскольку среднего РНР юзера очень сложно убедить отказаться от обращений к API напрямую, то лучше уж научить его, как это делать правильно.
У PDO свой собственный хитровыдуманный способ соединения, называемый DSN. Плюс во время коннекта можно задать хренову тучу опций, некоторые из которых чрезвычайно полезны. Полный список можно найти здесь, но важными из них являются только несколько.
Пример правильного соединения:
$host = ‘127.0.0.1’;
$db = ‘test’;
$user = ‘root’;
$pass = »;
$charset = ‘utf8’;
Что здесь происходит?
Плюс очень удобно задать FETCH_MODE по умолчанию, чтобы не писать его в КАЖДОМ запросе, как это очень любят делать прилежные хомячки.
Также здесь можно задавать режим pconnect-а, эмуляции подготовленных выражений и много других страшных слов.
Иногда, очень редко, может потребоваться второй способ, когда переменные сначала привязывают к запросу по одной, с помощью bindValue() / bindParam(), а потом только исполняют. В этом случае в execute() ничего не передается. Пример можно посмотреть в мануале
Используя этот метод, всегда следует предпочесть bindValue()? поскольку поведение bindParam() не очевидно для новичков и будет приводить к проблемам.
Также prepare() / execute() могут использоваться для многократного выполнения единожды подготовленного запроса с разными наборами данных. На практике это бывает нужно чрезвычайно редко, и особого прироста в скорости не приносит. Но на случай, если понадобится делать много однотипных запросов, то можно писать так:
$data = array(
1 => 1000,
5 => 300,
9 => 200,
);
Здесь мы один раз подготавливаем запрос, а затем много раз выполняем.
Но самой интересной функцией, с самым большим функционалом, является fetchAll(). Именно она делает PDO высокоуровневой библиотекой для работы с БД, а не просто низкоуровневым драйвером.
fetchAll() возвращает массив, который состоит из всех строк, которые вернул запрос. Из чего можно сделать два вывода:
1. Эту функцию не стоит применять тогда, когда запрос возвращает много данных. В таком случае лучше использовать традиционный цикл с fetch()
2. Поскольку в современных РНР приложениях данные никогда не выводятся сразу по получении, а передаются для этого в шаблон, fetchAll() становится просто незаменимой, позволяя не писать циклы вручную, и тем самым сократить количество кода.
Получение простого массива.
Вызванная без параметров, эта функция возвращает обычный индексированный массив, в котором лежат строки из бд, в формате, который задан в FETCH_MODE по умолчанию. Константы PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ могут менять формат на лету.
Всего различных режимов получения данных в PDO больше полутора десятков. Плюс ещё их можно комбинировать! Но это уже тема для отдельной статьи.
Работая с подготовленными выражениями, следует понимать, что плейсхолдер может заменять только строку или число. Ни ключевое слово, ни идентификатор, ни часть строки или набор строк через плейсхолдер подставить нельзя. Поэтому для LIKE надо сначала подготовить строку поиска целиком, а потом ее подставлять в запрос:
Ну, вы поняли. Тут тоже всё плохо. PDO не предоставляет вообще никаких средств для работы с идентификаторами, и их надо форматировать по-старинке, вручную (или посмотреть, все-таки, в сторону SafeMysql, в которой этот, как и многие другие вопросы, решены просто и элегантно).
Следует помнить, что правила форматирования идентификаторов отличаются для разных БД.
В mysql для ручного форматирования идентификатора необходимо выполнить два действия:
— заключить его в обратные одинарные кавычки (backticks, «`»).
— проискейпить эти символы внутри идентификатора внутри путём удвоения.
Однако, здесь есть один нюанс. Одного форматирования может быть недостаточно. приведенный выше код гарантирует нас от классической инъекции, но в некоторых случаях враг все равно может записать что-то нежелательное, если мы бездумно подставляем имена полей и таблиц прямиком в запрос. К примеру, есть в таблице users поле admin. Если входящие имена полей не фильтровать, то в это поле, при автоматическом формировании запроса из POST-а, любой дурак запишет любую гадость.
Поэтому имена таблиц и полей, приходящие от юзера, желательно проверять на допустимость, как в приведённом ниже примере
Это можно сделать, если принять соглашение, по которому имена полей в форме будут соответствовать именам полей в таблице. Тогда эти имена можно будет перечислить только один раз (в целях защиты от подмены, о которой говорилось выше), и использовать небольшую функцию-хелпер для сборки запроса, которая, в силу особенностей mysql, годится как для INSERT, так и UPDATE запросов:
Соответственно, для вставки код будет
Не слишком эффектно, но зато очень эффективно. Напомню, кстати, что если использовать Класс для безопасной и удобной работы с MySQL, то это всё делается в две строчки.
PDO и ключевые слова
Здесь кроме фильтрации ничего придумать невозможно. поэтому тупо прогонять все не прописанные в запросе напрямую операторы через белый список:
Класс PDO
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)
Введение
Представляет соединение между PHP и сервером базы данных.
Обзор классов
Содержание
User Contributed Notes 9 notes
«And storing username/password inside class is not a very good idea for production code.»
Good idea is to store database connection settings in *.ini files but you have to restrict access to them. For example this way:
my_setting.ini:
[database]
driver = mysql
host = localhost
;port = 3306
schema = db_schema
username = user
password = secret
I personnaly create a new instance of PDO like this :
$dbDatas = parse_ini_file( DB_FILE );
$dbOptions = [
\PDO::ATTR_DEFAULT_FECTH_MODE => \PDO::FETCH_OBJ,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
];
PDO and Dependency Injection
Dependency injection is good for testing. But for anyone wanting various data mapper objects to have a database connection, dependency injection can make other model code very messy because database objects have to be instantiated all over the place and given to the data mapper objects.
The code below is a good way to maintain dependency injection while keeping clean and minimal model code.
Starting with PHP 5.4 you are unable to use persistent connections when you have your own database class derived from the native PDO class. If your code uses this combination, you will encounter segmentation faults during the cleanup of the PHP process.
You can still use _either_ a derived PDO class _or_ persistent connections.
For more information, please see this bug report: https://bugs.php.net/bug.php?id=63176
Keep in mind, you MUST NOT use ‘root’ user in your applications, unless your application designed to do a database maintenance.
And storing username/password inside class is not a very good idea for production code. You would need to edit the actual working code to change settings, which is bad.
Here is an singleton PDO example:
[db_options]
PDO::MYSQL_ATTR_INIT_COMMAND=set names utf8
PHP: PDO быстрый старт, работа с MySQL
Содержание:
PDO (PHP Data Objects) — расширение PHP, которое реализует взаимодействие с базами данных при помощи объектов. Профит в том, что отсутствует привязка к конкретной системе управления базами данных. PDO поддерживает СУБД: MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server и другие.
Почему стоит использовать PDO
Тестовая база данных с таблицей
Установка PDO
Проверить доступные драйвера
Соединение с базой данных
Соединения устанавливаются автоматически при создании объекта PDO от его базового класса.
При ошибке подключения PHP выдаст ошибку:
Подготовленные и прямые запросы
В PDO два способа выполнения запросов:
Прямые запросы
Прямые запросы используются только в том случае, если в запросе отсутствуют переменные и есть уверенность, что запрос безопасен и правильно экранирован.
Подготовленные запросы
Как видно, в случае именованных плейсхолдеров в execute() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров. После этого можно извлечь результаты запроса:
Получение данных. Метод fetch()
Получение данных. Метод fetchColumn()
Получение данных. Метод fetchAll()
PDO и оператор LIKE
Работая с подготовленными запросами, следует понимать, что плейсхолдер может заменять только строку или число. Ни ключевое слово, ни идентификатор, ни часть строки или набор строк через плейсхолдер подставить нельзя. Поэтому для LIKE необходимо сначала подготовить строку поиска целиком, а потом ее подставлять в запрос:
Здесь может вознинуть проблема! Поиск может не работать, потому как из базы у вас приходят данные в неправильной кодировке. Необходимо добавить кодировку в подключение, если она там не указана!
PDO и оператор LIMIT
Решение #1 : Отключить режим эмуляции:
PDO и оператор IN
При выборке из таблицы необходимо доставать записи, соответствующие всем значениям массива.
Добавление записей
Изменение записей
Удаление записей
Использование транзакций
Важно! Транзакции в PDO работают только с таблицами InnoDB
В данной заметке мы познакомились с основными понятиями PDO, его установкой, подключением к БД и самые простые возможности выборки, изменения и удаления данных. В следующих заметках мы рассмотрим ещё несколько тем, касающихся PDO.