1. Главная страница » Компьютеры

Fetchall pdo fetch assoc

Автор: | 16.12.2019

Как уже говорилось в статье Как работать с PDO?, константы, задающие режим получения данных (наряду с передачей параметров напрямую в execute() ) делают PDO по-настоящему удобной библиотекой для работы с БД, а не просто еще одним (пусть и универсальным) API для доступа к базе данных. С помощью этих констант можно значительно сократить код многих рутинных операций, поскольку они позволяют получить данные сразу в нужном формате.

Хотя интересующие нас константы частично описываются на страницах документации, посвященных методам fetch() и fetchAll() , полный список приведен только на странице с общим списком констант PDO, что не кажется мне очень удобным, и может являться той причиной, по которой некоторые особенно интересные режимы получения данных оказались вне поля зрения большинства разработчиков. Я решил выделить интересующие нас константы из общего списка и разбить для удобства на несколько категорий, поскольку их количество впечатляет — ни много ни мало, а целых 25 штук!

Классика

Для начала перечислим константы, которые дублируют стандартное поведение теплых ламповых функций mysql. Все примеры даются с использованием функции var_export() .

PDO::FETCH_BOTH

аналог mysql_fetch_array() . Все данные возвращаются в дублированном виде — и с текстовыми индексами, и с цифровыми. Этот режим включен в PDO по умолчанию.

PDO::FETCH_NUM

снова старый знакомый, аналог mysql_fetch_row() . Только цифровые индексы:

PDO::FETCH_ASSOC

то же самое, аналог mysql_fetch_assoc() , только текстовые индексы.

Читайте также:  Personal power на русском

PDO::FETCH_OBJ

аналог mysql_fetch_object() без указания имени класса, возвращает экземпляр stdClass

PDO::FETCH_LAZY

Эта константа настолько примечательна и ни на что не похожа, что я решил вынести её в отдельный раздел. Начнем с того, что возвращаемая с её помощью переменная является экземпляром особенного класса PDORow , причем этот объект наделён целым ворохом уникальных свойств:

  • Во-первых, эта переменная не содержит сами запрошенные данные, а отдаёт их по запросу (на что намекает название)
  • Во-вторых, помимо запрошенных данных, в объекте присутствует загадочная переменная, которая называется queryString и содержит SQL запрос(!) (что намекает о родственности этого класса PDOStatement):

Для пытливых — да, перезаписать queryString можно 🙂

  • В-третьих, эту переменную невозможно сохранить в сессии (или, другими словами — сериализовать)
  • В-четвертых, получать из неё данные можно как угодно, любым из трёх способов: через числовой индекс, ассоциативный, или обращаясь к свойству класса через ->
  • В-пятых, обращение к несуществующим свойствам не вызывает нотис Undefined property / index. Молча возвращается NULL .
  • В-шестых, эта переменная меняет своё состояние от последующих вызовов fetch() с другими константами. Плюс ко всему, эта константа не работает с fetchAll() , а только с fetch() .
  • Проведём пару экспериментов. Попробуем запросить относительно большой объём данных, и посмотрим, как меняется потребление памяти, и заодно проверим ещё пару утверждений:

    Как видно, этот код опрашивает нашу таблицу users, добавляя к строке мегабайтное поле. После этого мы получаем строку через эту константу — объём памяти не поменялся. Только после того, как мы присваиваем значение мегабайтного поля переменной — он увеличивается. Для контроля выводим имя из таблицы users. Затем получаем ещё одну строку, уже в одном из стандартных режимов. Видим, что объем памяти тут же подскакивает, в отличие от предыдущего случая. Экономия в первом случае налицо! Так же мы видим отсутствие нотиса и смену состояния $lazy после вызова fetch() .

    Из всей этой информации можно сделать вывод, что объект PDORow — это канал прямой связи с астралом resultSet-ом драйвера БД. И, не имея собственного состояния, попросту читает данные с текущей позиции курсора. Учитывая всё вышесказанное можно только удивляться, почему эта константа до сих пор так редко используется.

    Самое полезное

    Здесь я решил собрать самые полезные, на мой взгляд, режимы, которые возвращают данные в наиболее востребованных в повседневной разработке форматах.

    Примечание: здесь и далее все примеры даются при включенном по умолчанию формате вывода PDO::FETCH_ASSOC

    PDO::FETCH_COLUMN

    Вытаскивает только одну колонку из результата. Соответственно, имеет смысл только при использовании с fetchAll() — и в этом случае возвращает сразу одномерный массив. Очень удобно.

    Дополнительным параметром можно указать номер выбираемой колонки. Если этот флаг используется сам по себе, то номер указывать нет смысла (надо сразу в запросе выбирать только одну колонку, которая и будет выведена), но если в комбинации с другими, то номер может оказаться полезным.

    PDO::FETCH_KEY_PAIR

    Малоизвестный, но довольно полезный режим, когда из двух запрошенных полей содержимое первого становится ключом, а второго — значением одномерного массива.

    Требователен к количеству колонок в запросе — их должно быть строго две

    PDO::FETCH_UNIQUE

    похож на предыдущий, но в качестве значения возвращает всю оставшуюся строку. C fetch() этот режим не возвращает ничего вразумительного, а вот с fetchAll() как раз получается такой, весьма востребованный режим. Главное, чтобы первой колонкой в запросе выбиралось уникальное поле — тогда оно будет использовано в качестве индекса возвращаемого массива, вместо обычной нумерации

    PDO::FETCH_GROUP

    Группирует значения по первой колонке. К примеру, нижеследующий код разобьёт пользователей на мальчиков и девочек, и положит их в разные массивы:

    То есть, этот режим идеально подходит для классической задачи "вывести события сгруппированные по дням" (или "вывести товары, сгруппированные по категориям"). Также может комбинироваться с PDO::FETCH_COLUMN :

    Объектное ориентирование

    Разумеется, простым stdObject возможности (я бы даже сказал — аппетиты) PDO по работе с объектами не исчерпываются. Дальше идет целая серия режимов для всевозможной манипуляции ими.

    PDO::FETCH_CLASS

    Создаёт объект указанного класса, заполняя его свойства данными из БД. Однако здесь, увы, начинаются неудобства и непоследовательность в работе вызывающих функций. Если для fetchAll() можно написать красиво и компактно

    то для fetch() приходится писать такую колбасу:

    Из-за того что fetch() не позволяет передать имя класса, мы вынуждены пользоваться setFetchMode() . А учитывая, что эта функция возвращает булево значение, а не ссылку на объект, мы не можем использовать method chaining. Пичаль. Также следует помнить, что в этом режиме PDO будет вызывать магический метод __set() если свойство, совпадающее с именем поля, не найдено в объекте. Для PHP это означает, что если в объекте отсутствует такой метод, то все колонки строки, полученной из БД, будут назначены переменным класса. Если же мы хотим присвоить значения только существующим переменным, то этот момент надо контролировать с помощью метода __set() . Например

    в то время как у класса с пустым __set() будут заполнены только существующие свойства:

    Можно, кстати, заметить, что PDO присваивает значения и приватным свойствам, что несколько неожиданно, но очень удобно.

    PDO::FETCH_CLASSTYPE

    Очень интересная константа. Представляет собой не самостоятельный режим получения данных, а флаг-модификатор, изменяющий поведение других режимов. При её использовании PDO будет брать имя класса из первой колонки полученных из БД данных. То есть, с её помощью код для fetch() можно сделать короче

    PDO::FETCH_PROPS_LATE

    Ещё один флаг-модификатор. По умолчанию PDO присваивает значения свойствам класса до вызова конструктора. При помощи же данной константы это поведение можно изменить — сначала будет вызываться конструктор:

    PDO::FETCH_INTO

    в отличие от PDO::FETCH_CLASS не создаёт новый объект, а обновляет существующий. Соответственно, в качестве параметра передается переменная с объектом. По очевидным причинам имеет смысл только с fetch()

    Как видно, fetch() возвращает тот же объект, что представляется мне несколько избыточным. Также, с сожалением приходится констатировать, что в отличие от PDO::FETCH_CLASS , этот режим не присваивает значения приватным свойствам.

    PDO::FETCH_SERIALIZE

    ещё один флаг для PDO::FETCH_CLASS . Должен возвращать объект, который хранился в БД в сериализованном виде. Конструктор не вызывается. На данный момент не работает. Должно быть что-то вроде такого

    Этот режим попил у меня крови изрядно. Описание у него самое невинное — "то же самое, что и PDO::FETCH_INTO, но объект передается в сериализованном массиве". А куда передавать-то? В параметры что ли? пробовал и так, и сяк — ничего не получалось. Только когда нашел юнит-тест, посвященный этому режиму, стало понятно, что объект должен придти из БД. Но всё равно не получается — пишет, "cannot unserialize class".

    В общем, предполагается, что этот режим должен создавать объект из сериализованного представления, хранящегося в БД. Но это не работает, поскольку при использовании этого метода из базы возвращается не то, что туда клали! Вместо исходного объекта возвращается внонимный класс, который содержит два свойства — одно с именем объекта, и второе с исходным объектом. В общем, мы с zerkms-ом покопались, и в итоге он накатал баг-репорт, https://bugs.php.net/bug.php? >

    Разное

    PDO::FETCH_FUNC

    для любителей замыканий. Работает только внутри fetchAll() . В параметры функции PDO передаёт переменные для каждого полученного поля, что может быть неудобным — нет доступа к именам полей, а только к значениям. К примеру, эмуляция работы PDO::FETCH_COLUMN:

    PDO::FETCH_NAMED

    почти то же самое, что PDO::FETCH_ASSOC , но с одним отличием. Много раз я встречал на форумах вопросы о том, как получить значения полей с одинаковыми именами из разных таблиц при джойне. Всегда ответ был один — писать алиасы руками в запросе или использовать цифровые индексы. А вот и ответ от PDO: получение данных в этом режиме аналогично PDO::FETCH_ASSOC, но если встречаются поля с одинаковыми именами, то все значения по очереди записываются во вложенный массив. Допустим, у нас есть таблицы users и companies, причем в обеих есть поле name. Если получать данные традиционным путём, то одно из полей будет съедено:

    Если же указать это флаг, то все значения колонок с совпадающими именами будут собраны во вложенном массиве в порядке поступления:

    Уж не знаю, насколько это востребованная фича, и насколько легче разбирать массив, нежели прописать алиасы в запросе.

    PDO::FETCH_BOUND

    очень интересный режим, сильно отличающийся от других. В отличие от всех остальных, он не возвращает не массив или объект. Вместо этого он присваивает значения переменным, предварительно указанным с помощью bindColumn() — режим, аналогичный тому, что используется в mysqli при получении данных из подготовленного запроса. Пример есть в документации

    Untested

    За неимением подходящей БД я не смог проверить работу еще нескольких констант. Но, на мой взгляд, их поведение достаточно очевидно и не нуждается в особом описании.

    • PDO::ATTR_FETCH_CATALOG_NAMES — возвращает имена колонок в формате "каталог.имя_колонки". Поддерживается не всеми драйверами.
    • PDO::ATTR_FETCH_TABLE_NAMES — возвращает имена колонок в формате "имятаблицы.имяколонки". Поддерживается не всеми драйверами.
    • PDO::FETCH_ORI_* — 6 функций по управлению курсором при получении данных из БД. Пример есть в документации

    В прошлой заметке мы познакомились с основами PDO и простейшими запросами выборки данных из базы данных. В этой заметке мы научимся управлять режимами получения данных.

    Все предопределенные константы здесь

    PDO::FETCH_BOTH

    Аналог mysql_fetch_array() . Все данные возвращаются в дублированном виде, с текстовыми индексами и цифровыми. Этот режим включен в PDO по умолчанию.

    PDO::FETCH_NUM

    Аналог mysql_fetch_row() . Только цифровые индексы:

    PDO::FETCH_ASSOC

    Аналог mysql_fetch_assoc() Только текстовые индексы.

    PDO::FETCH_OBJ

    Аналог mysql_fetch_object() без указания имени класса, возвращает экземпляр stdClass

    PDO::FETCH_LAZY

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

    PDO::FETCH_COLUMN

    Когда необходимо получить только одну колонку из результата. Соответственно, имеет смысл только при использовании с fetchAll() — и в этом случае возвращает сразу одномерный массив.

    PDO::FETCH_KEY_PAIR

    Малоизвестный, но очень полезный режим, когда из двух запрошенных полей содержимое первого становится ключом, а второго — значением одномерного массива.

    PDO::FETCH_UNIQUE

    Похож на предыдущий, но в качестве значения возвращает всю оставшуюся строку. C fetch() этот режим не возвращает ничего вразумительного, а вот с fetchAll() как раз получается такой, весьма востребованный режим. Главное, чтобы первой колонкой в запросе выбиралось уникальное поле — тогда оно будет использовано в качестве индекса возвращаемого массива, вместо обычной нумерации

    PDO::FETCH_GROUP

    Группирует значения по первой колонке. К примеру, нижеследующий код разобьёт пользователей на мальчиков и девочек, и положит их в разные массивы:

    То есть, этот режим идеально подходит для классической задачи вывести события сгруппированные по дням (или вывести товары, сгруппированные по категориям). Также может комбинироваться с PDO::FETCH_COLUMN :

    PDO::FETCH_CLASS

    Создаёт объект указанного класса, заполняя его свойства данными из БД. Однако здесь, увы, начинаются неудобства и непоследовательность в работе вызывающих функций. Если для fetchAll() можно написать красиво и компактно

    то для fetch() приходится писать такую колбасу:

    Из-за того что fetch() не позволяет передать имя класса, мы вынуждены пользоваться setFetchMode() . А учитывая, что эта функция возвращает булево значение, а не ссылку на объект, мы не можем использовать method chaining. Также следует помнить, что в этом режиме PDO будет вызывать магический метод __set() если свойство, совпадающее с именем поля, не найдено в объекте. Для PHP это означает, что если в объекте отсутствует такой метод, то все колонки строки, полученной из БД, будут назначены переменным класса. Если же мы хотим присвоить значения только существующим переменным, то этот момент надо контролировать с помощью метода __set() . Например

    в то время как у класса с пустым __set() будут заполнены только существующие свойства:

    Можно, кстати, заметить, что PDO присваивает значения и приватным свойствам, что несколько неожиданно, но очень удобно.

    PDO::FETCH_CLASSTYPE

    Очень интересная константа. Представляет собой не самостоятельный режим получения данных, а флаг-модификатор, изменяющий поведение других режимов. При её использовании PDO будет брать имя класса из первой колонки полученных из БД данных. То есть, с её помощью код для fetch() можно сделать короче

    PDO::FETCH_PROPS_LATE

    Ещё один флаг-модификатор. По умолчанию PDO присваивает значения свойствам класса до вызова конструктора. При помощи же данной константы это поведение можно изменить — сначала будет вызываться конструктор:

    PDO::FETCH_INTO

    В отличие от PDO::FETCH_CLASS не создаёт новый объект, а обновляет существующий. Соответственно, в качестве параметра передается переменная с объектом. По очевидным причинам имеет смысл только с fetch()

    Как видно, fetch() возвращает тот же объект, что представляется мне несколько избыточным. Также, с сожалением приходится констатировать, что в отличие от PDO::FETCH_CLASS , этот режим не присваивает значения приватным свойствам.

    PDO::FETCH_SERIALIZE

    Ещё один флаг для PDO::FETCH_CLASS . Должен возвращать объект, который хранился в БД в сериализованном виде. Конструктор не вызывается. На данный момент не работает. Должно быть что-то вроде такого

    PDO::FETCH_FUNC

    Для любителей замыканий. Работает только внутри fetchAll() . В параметры функции PDO передаёт переменные для каждого полученного поля, что может быть неудобным — нет доступа к именам полей, а только к значениям. К примеру, эмуляция работы PDO::FETCH_COLUMN :

    PDO::FETCH_NAMED

    Почти то же самое, что PDO::FETCH_ASSOC , но с одним отличием. Много раз я встречал на форумах вопросы о том, как получить значения полей с одинаковыми именами из разных таблиц при джойне. Всегда ответ был один — писать алиасы руками в запросе или использовать цифровые индексы. А вот и ответ от PDO: получение данных в этом режиме аналогично PDO::FETCH_ASSOC , но если встречаются поля с одинаковыми именами, то все значения по очереди записываются во вложенный массив. Допустим, у нас есть таблицы users и companies, причем в обеих есть поле name. Если получать данные традиционным путём, то одно из полей будет съедено:

    Если же указать это флаг, то все значения колонок с совпадающими именами будут собраны во вложенном массиве в порядке поступления:

    PDO::FETCH_BOUND

    Очень интересный режим, сильно отличающийся от других. В отличие от всех остальных, он не возвращает не массив или объект. Вместо этого он присваивает значения переменным, предварительно указанным с помощью bindColumn() — режим, аналогичный тому, что используется в mysqli при получении данных из подготовленного запроса. Пример есть в документации

    Материал подготовлен на основе официальной статьи .

    Я пытаюсь создать веб-приложение с помощью PHP, и я использую memcached для хранения пользовательских данных из БД.

    Например, скажем, что у меня есть этот код:

    Я не уверен, как читать переменную $user и получать данные из нее. Мне нужно будет прочитать столбец электронной почты и пароля.

    Я надеялся, что кто-то сможет объяснить мне, как это работает.

    PDOStatement :: fetch возвращает строку из набора результатов. Параметр PDO::FETCH_ASSOC сообщает PDO возвращать результат как ассоциативный массив.

    Ключи массива будут соответствовать вашим именам столбцов. Если ваша таблица содержит столбцы «электронная почта» и «пароль», массив будет структурирован следующим образом:

    Чтобы прочитать данные из столбца «email», выполните следующие действия:

    Цикл через массив, как и любой другой ассоциативный массив:

    Чтобы прочитать результат, вы можете прочитать его как простой php-массив.

    Например, получить name можно, например, $user[‘name’] и так далее. Метод fetch(PDO::FETCH_ASSOC) возвращает только 1 кортеж tho. Если вы хотите получить все кортежи, вы можете использовать fetchall(PDO::FETCH_ASSOC) . Вы можете пройти через многомерный массив и получить значения одинаковыми.

    PDO:FETCH_ASSOC помещает результаты в массив, где значения отображаются на их имена полей.

    Вы можете получить доступ к полю name следующим образом: $user[‘name’] .

    Я рекомендую использовать PDO::FETCH_OBJ . Он извлекает поля в объекте, и вы можете получить доступ так: $user->name

    возвращает словарь . Вы можете просто получить электронную почту и пароль:

    возвращает список словарей

    / * Шаблон проектирования «шлюз данных таблицы данных» * /

    / * Печатать всю строку только с помощью столбца ‘user_id’ * /

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

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