Использование PDO в PHP

PDO это аббревиатура от PHP Data Objects. Данное расширение предоставляет нам доступ к Базам Данных используя объекты. И в этой статье мы подробно рассмотрим, как работать с этим расширением, что в нем хорошего и плохого. Велкам.

Прежде чем начать разговор о PDO, давайте разберемся, чем нас не устраивают mysql и mysqli. Ну, mysql не устраивает хотя бы тем, что оно уже объявлено deprecated, и в новых версиях поддерживаться не будет. Mysqli – более новое расширение, которое имеет ряд преимуществ, перед его предшественником mysql и прекрасно работает, но… Если вы начинаете разработку нового проекта и выбираете, что использовать: mysqli или PDO, вы должны выбрать PDO и вот почему.

Во-первых, приложения на PHP уже стали объектно-ориентированными, и PDO реализует именно объектно-ориентированный подход к работе с БД. Это сильно упрощает работу с кодом, его масштабируемость и поддержку, а так же стандартизированность, если можно так выразиться. Во-вторых, и это более важно, PDO – это высокоуровневый интерфейс доступа к Базе данных, но не обязательно к MySQL. PDO поддерживает множество разных баз данных: MySQL, PostgreSQL, SQLite, MSSQL и другие. Если одним прекрасным утром вы решите переехать с MySQL в PostgreSQL, то вам нужно будет заменить всего-лишь одну строчку, а не переписывать весь код. В третьих, в PDO есть такая штука, как “биндинг” параметров. Далее вы узнаете, что это. Пока лишь скажем, что это позволяет легче “конструировать” сложные запросы динамически и обеспечивает защиту от SQL-инъекций.

 

Установка соединения с базой

Для установки соединения с базой данных с помощью PDO, вам нужно инициализировать объект PDO следующим образом:

Конструктор принимает три параметра:

  1. Так называемая строка dsn. В ней указан драйвер подключения к базе, хост, имя базы и кодировка.
  2. Логин
  3. Пароль

 

Запросы

В отличие от привычных тебе mysql_query (или mysqli_query), в PDO для совершения запросов есть два метода: один используется для запросов, которые возвращают результат (select, show), второй – для запросов, не возвращающих результат (insert, update, delete…).

Выполнение запросов

Вот, простой пример вставки данных:

Тут нужно еще обратить внимание на один нюанс. Запрос у нас на вставку (INSERT), выше я говорил о том, что он не возвращает результат. Это так. Но речь идет о результате возвращаемом Базой данных. Там его действительно нет. Но функция exec() вам кое-что возвращает – это значение affected_rows, кол-во обработанных строк.

Выборка данных

Давайте вспомним, как вы выбирали данные, с помощью mysql_query() :

С помощью PDO это будет выглядеть следующим образом, как по мне более интуитивно понятным.

Конечно, вы можете получать данные  не только в виде ассоциативного массива, но и нумерованного массива, объекта и даже класса. Для этого, нужно установить fetching_mode, с помощью одной из констант PDO::FETCH_* . Например:

Вот какие могут быть варианты значений:

  • PDO::FETCH_ASSOC  — возвращает ассоциативный массив. В примере выше, чтобы получить id нужно использовать  $row['id'] 
  • PDO::FETCH_NUM  — возвращает нумерованный массив. В примере выше, чтобы получить id нужно использовать $row[0] ;
  • PDO::FETCH_OBJ  — возвращает объект. Для получения id вызываем $row->id ;
  • PDO::FETCH_CLASS  — возвращает экземпляр заранее указанного класса, при этом выбранные данные (поля таблицы в БД) будут соответствовать соответствующим полям (свойствам) класса.

И это еще не полный список. Чтоб ознакомится с полным списком, идите читайте документацию.

Примечание: Рекомендуется всегда указывать FETCH_MODE, в противном случае по умолчанию будет указан FETCH_BOTH, что означает, что данные будут доступны в двух вариантах, как ассоциативный массив, и как обычный массив, что расходует ровно в 2 раза больше памяти.

Наверняка вы обратили внимание на константу FETCH_CLASS. Да, это супер возможность. Давайте посмотрим на нее поближе.

Допустим, вот наш класс User:

Давайте еще раз выберем те же данные, но на этот раз используя класс User, который в данном случае будет являться Моделью (Model) или сущностью (Entity).

 

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

Для того, чтобы понять биндинг параметров и его преимущества, нужно более глубоко разобраться в том, как работает PDO. Когда мы вызывали  $statement->query() выше, PDO “готовил” запрос, выполнял его и возвращал нам результат.

Когда вы вызываете  $connection->prepare() вы создаете prepared statement (подготовленный запрос). Подготовленные запросы, это такая фича, с помощью которой вы можете конструировать запрос как шаблон, компилировать его и выполнять, заменяя специальные метки (placeholders) значениями.

Когда, позже, вы вызываете  $statement->execute() , вы заменяете плэйсхолдеры конкретными значениями и выполняете запрос. Это похоже на функцию render() в шаблонизаторах.

Проще понять всю эту билиберду на примере:

Вот, здесь мы создали подготовленный запрос, :id  – это наш плэйсхолдер, метка, которую мы потом заменим на конкретное значение. Фишка в том, что данная строка не меняется в зависимости от того, какой-то ID будет стоять. В зависимости от настроек вашего приложения, она может быть даже закеширована, что положительно скажется на быстродействии вашего приложения.

Давайте выполним запрос:

И получим результат:

Готово!

Преимущества биндинга

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

Одно из таким преимуществ, например, в том, что PDO берет на себя задачу по фильтрации и нормализации данных, которые используются в запросе. Вспомните, как вы защищались от sql-инъекций и делали нормализацию данных в mysql:

А вот, как это будет выглядеть в PDO:

Еще можно использовать неименованные плэйсхолдеры. Так запись выглядит короче:

Когда мы вызываем метод prepare(), PDO парсит запрос и кеширует его для дальнейшего использования. Когда в нашем цикле мы снова вызываем execute(), запрос уже не создается. Мы только подставляем новое значение. Как я уже говорил, это положительно сказывается на быстродействии приложения.

Так же вы могли заметить, что я использовал метод fetchColumn(), о котором ничего не говорил еще. Настало время. Этот метод возвращает значение первого поля. Он очень удобен, когда нам нужно выполнить count(), sum(), min(), max() и другие подобные запросы.

Биндинг значений в условие IN

Многие программисты, которые впервые сталкиваются с PDO и доходят до ситуации с использованием условия IN() сталкиваются с некоторыми проблемами. Представьте, что мы составили строку из значений разделенных запятыми из айдишников пользователей, которых хотим достать из базы.

Большинство делают следующее:

Но, друг мой, спешу тебя огорчить, так работать не будет. Вы можете подставлять только скалярные значения: integer, sting etc. Вы мне возразите, что мол, дык я ж и передаю строку, в чем проблема. В том, что эта строка PDO автоматически оборачивается в кавычки, а если сама имеет кавычки – они экранируются, и в IN передается что-то вроде IN("1,2,3") .

Как вариант, вы можете генерировать не значения, а именно плейсхолдеры и заменять их значениями, вот так:

Понимаете что тут произошло? Мы сгенерировали строку из плейсхолдеров, типа ?,?,?,? , а в метод execute() передали массив из 4 значений, которыми будут заменены наши знаки вопроса.

Определение типа значения при биндинге параметров

Последняя фича, на которой мы остановимся – это возможность определять типа значений, который мы передаем. Зачем?

  • Читабельность кода: элементарно, чтобы видеть, значение какого типа туда должно попадать
  • Надежность: строгость в параметрах всегда приводит к более надежному коду. Так же вам легче будет найти ошибку, если вдруг вместо числового значения, в запрос придет строка.
  • Скорость: когда вы указываете тип значения, вы избавляете базу данных от работы связанной с приведением типов.

Для установки параметров с указанием какого они типа, используется метод bindValue() .

 

Заключение

PDO – это не новинка. Но до сих пор еще не все программисты постигли его прелести. Друзья, если вы только начинаете свой путь или по каким-то причинам еще не пользовались PDO – начинайте. PHP развивается и PDO это новый (ну по крайней мере последний) способ общения с базой данных, предлагающий вам работать с БД в объектно-ориентированном стиле, пользуйтесь им. Что еще тут скажешь… Пишите комменты, у кого были трудности в переезде на PDO или в его использовании. Делитесь опытом, подводными камнями, на которые вы наталкивались!

Удачи!

 

 

 

 

 

 

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *