Обеспечивает методы для подготовки выражений и работы с объектами, которые могут сделать Вашу работу более продуктивной!

Введение в PDO

"PDO - PHP Data Objects - это уровень для доступа к базам данных, который обеспечивает унифицированные методы для доступа к различным базам данных."

Он не зависит от специфического синтаксиса базы данных и позволяет легко переключаться на другой тип баз данных и платформу простым изменением строки подключения в большинстве случаев.

Данный урок не является описанием процесса работы с SQL . Он предназначен для тех, кто использует расширения mysql или mysqli , чтобы помочь им перейти к более мощному и портируемому PDO.

Поддержка баз данных

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

  • PDO_DBLIB (FreeTDS / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix Dynamic Server)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle Call Interface)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC и win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 и SQLite 2)
  • PDO_4D (4D)

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

Print_r(PDO::getAvailableDrivers());

Подключение

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


try { # MS SQL Server и Sybase с PDO_DBLIB $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass"); $DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass"); # MySQL с PDO_MYSQL $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = new PDO("sqlite:my/database/path/database.db"); } catch(PDOException $e) { echo $e->getMessage(); }

Обратите внимание на блок try/catch - всегда нужно оборачивать операции PDO в блок try/catch и использовать механизм исключений. Обычно выполняется только одно подключение, в нашем примере показаны несколько подключений для отображения синтаксиса. $DBH содержит дескриптор базы данных и будет использоваться на протяжении всего нашего урока.

Вы можете закрыть любое соединение установкой дескриптора в null .

# Закрываем соединение $DBH = null;

Вы можете узнать больше о специфических опциях и строках подключения для различных баз данных из документов с сайта PHP.net .

Исключения и PDO

PDO может использовать исключения для обработки ошибок. Значит все операции PDO должны быть заключены в блок try/catch . PDO может выдавать ошибки трех уровней, уровень контроля ошибок выбирается установкой атрибута режима контроля ошибок для дескриптора базы данных:

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

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

PDO::ERRMODE_SILENT

Уровень контроля ошибок, устанавляваемы по умолчанию. На этом уровене ошибки генерируются по такому же принципу, как в расширениях mysql или mysqli . Два других уровня контроля ошибок более подходят для стиля програмирования в стиле DRY (Don"t Repeat Youself - не повторяй сам себя).

PDO::ERRMODE_WARNING

На данном уровне контроля ошибок генеррируются стандартные предупреждения PHP, при этом программа может продолжать выполение. Данный уровень удобен для отладки.

PDO::ERRMODE_EXCEPTION

Данный уровень контроля ошибок следует использовать в большинстве ситуаций. Генерируются исключения, которые позволяют аккуратно обрабатывать ошибки и скрывать данные, которые могут помочь кому-нибудь взломать Вашу систему. Ниже приведен пример, демонстрирующий преимущества исключений:

# Подключаемся к базе данных try { $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); # Ошибочно набираем DELECT вместо SELECT! $DBH->prepare("DELECT name FROM people"); } catch(PDOException $e) { echo " Извините. Но операция не может быть выполнена."; file_put_contents("PDOErrors.txt", $e->getMessage(), FILE_APPEND); }

Здесь сделана преднамеренная ошибка в выражении SELECT. Это вызовет исключение. Исключение отправит описание ошибки в log файл и выдаст сообщение пользователю.

Вставка и обновление данных

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


Здесь приведен пример наиболее используемого типа вставки данных:

# STH - это "дескриптор состояния" $STH = $DBH->prepare("INSERT INTO folks (first_name) values ("Cathy")"); $STH->execute();

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

Подготовленные выражения

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

Вы можете использовать подготовленные выражения с помощью включения шаблонов в ваш код SQL. Ниже приводятся 3 примера: один без шаблонов, один с неименованными шаблонами, один с именоваными шаблонами.

# нет шаблонов - открыто для атак путем внедрения SQL кода! $STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)"); # неименованые шаблоны $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?); # именованые шаблоны $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");

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

Неименованные шаблоны # назначение переменных каждому шаблону, индексируются от 1 до 3 $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $city); # Вставляем одну строку $name = "Дима" $addr = "ул. Лизюкова"; $city = "Москва"; $STH->execute(); # Вставляем другую строку $name = "Сеня" $addr = "Коммунистический тупик"; $city = "Питер"; $STH->execute();

Операция проходит в два этапа. На первом этапе шаблонам назначаются переменные. Затем, пременным присваиваются значения и выполняем выражение. Чтобы послать следующую порцию данных, нужно изменить значения переменных и выполнить выражение снова.

Выглядит несколько громоздко для выражений с большим количеством параметров? Конечно. Однако, если Ваши данные храняться в массиве, то все будет очень коротко:

# Данные, которые надо вставить $data = array("Моня", "проспект Незабудок", "Закутайск"); $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?)"); $STH->execute($data);

Данные в массиве подставляются в шаблоны в порядке следования. $data идет в первый шаблон, $data - во второй, и так далее. Однако, если массив проиндексирован в другом порядке, то такая операция будет выполняться некорректно. Вам нужно следить за соответствием порядка следования шаблонов и порядком расположения данных в массиве.

Именованные шаблоны

Вот пример использования именованного шаблона:

# Первый аргумент функции - имя именованного шаблона # Именованный шаблон всегда начинается с двоеточия $STH->bindParam(":name", $name);

Вы можете использовать сокращения, но они работают с ассоциированными массивами. Пример:

# Данные, которые надо вставить $data = array("name" => "Мишель", "addr" => "переулок Кузнечный", "city" => "Cnjkbwf"); # Сокращение $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); $STH->execute($data);

Ключи Вашей таблицы не нуждаются в двоеточии, но тем не менее должны соответствовать именам шаблонов. Если Вы используете массив массивов, то можно проходить по нему и просто вызывать execute для каждого массива данных.

Другая приятная особенность именованых шаблонов - способность вставлять объекты прямо в вашу базу данных, при совпадении свойств и имен полей. Пример:

# Простой объект class person { public $name; public $addr; public $city; function __construct($n,$a,$c) { $this->name = $n; $this->addr = $a; $this->city = $c; } # и т.д. ... } $cathy = new person("Катя","проспект Ленина","Можайск"); # Выполняем: $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); $STH->execute((array)$cathy);

Преобразование типа объекта к array в execute приводит к обработке свойств как ключей массива.

Получение данных

Для получения данных используется метод идентификатора состояния ->fetch() . Перед вызовом метода fetch() нужно указать PDO как Вы будете доставать данные из базы. Можно выбрать следующие опции:

  • PDO::FETCH_ASSOC : возвращает массив, индексированный по именам столбцов
  • PDO::FETCH_BOTH (default) : возвращает массив, индексированный по именам столбцов и по номерам
  • PDO::FETCH_BOUND : назначает значения ваших столбцов набору переменных с использованием метода ->bindColumn()
  • PDO::FETCH_CLASS : назначает значения столбцов свойствам именованного класса, если соответствующего свойства не существует - оно создается
  • PDO::FETCH_INTO : обновляет существующий экземпляр именованного класса
  • PDO::FETCH_LAZY : комбинация PDO::FETCH_BOTH/PDO::FETCH_OBJ , создает имена переменных объекта так как они используются
  • PDO::FETCH_NUM : возвращает массив, индексированный по номерам столбцов
  • PDO::FETCH_OBJ : возвращает анонимный объект с именами свойств, соответствующих именам столбцов

В действительности основные ситуации разрешаются с помощью трех опций: FETCH_ASSOC , FETCH_CLASS и FETCH_OBJ . Для установки метода извлечения данных используется:

$STH->setFetchMode(PDO::FETCH_ASSOC);

Также можно устанавливать метод извлечения данных непосредственно в вызове метода ->fetch() .

FETCH_ASSOC

Данный тип извлечения данных создает ассоциативный массив, индексированный по именам столбцов. Он должен быть достаточно хорошо известен тем, кто пользуется расширениями mysql/mysqli . Пример выборки данных:

$STH = $DBH->query("SELECT name, addr, city from folks"); # Устанавливаем режим извлечения данных $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) { echo $row["name"] . "\n"; echo $row["addr"] . "\n"; echo $row["city"] . "\n"; }

Цикл while продолжает перебирать результат выборки по одной строке до полного завершения.

FETCH_OBJ

При данном типе извлечения данных создается объект класса std для каждой строки полученных данных:

$STH = $DBH->query("SELECT name, addr, city from folks"); # Устанавливаем режим извлечения данных $STH->setFetchMode(PDO::FETCH_OBJ); # показываем результат while($row = $STH->fetch()) { echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . "\n"; }

FETCH_CLASS

При данном типе извлечения данные помещаются прямо в класс, который Вы выбирете. При использовании FETCH_CLASS свойства вашего объекта устанавливаются ДО вызова конструктора. Это очень важно. Если свойства соответствующего имени столбца не существует, то такое свойство будет создано (как public ) для Вас.

Это означает, что если данные нуждаются в трансформации после извлечения из базы данных, то она может быть выполнена автоматически Вашим объектом, как только таковой будет создан.

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

Class secret_person { public $name; public $addr; public $city; public $other_data; function __construct($other = "") { $this->address = preg_replace("//", "x", $this->address); $this->other_data = $other; } }

Как только данные извлечены в класс, все символы a-z в нижнем регистре в адресе будут заменены символом x. Теперь с использованием класса и получением данных трансформация происходит полностью прозрачно:

$STH = $DBH->query("SELECT name, addr, city from folks"); $STH->setFetchMode(PDO::FETCH_CLASS, "secret_person"); while($obj = $STH->fetch()) { echo $obj->addr; }

Если адрес был ’Ленинский пр-т 5’ Вы увидите ’Лхххххххх хх-х 5’. Конечно, существуют ситуации, когда Вы хотите, чтобы конструктор был вызван перед тем, как будут назначены данные. PDO имеет средства реализовать это:

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "secret_person");

Теперь, когда Вы повторите предыдущий пример при установленом режиме PDO::FETCH_PROPS_LATE адрес не будет скрыт, так как конструктор был вызван и свойства назначены.

Если Вам нужно, то можно передавать аргументы конструктору при извлечении данных в объект:

$STH->setFetchMode(PDO::FETCH_CLASS, "secret_person", array("stuff"));

Если Вам нужно передать различные данные в конструктор для каждого объекта, Вы можете устанавливать режим извлечения данных внутри метода fetch :

$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) { // do stuff $i++ }

Некоторые другие полезные методы

Так как в короткой статье нельзя описать PDO полностью, то представим несколько полезных методов для выполнения базовых операций.

$DBH->lastInsertId();

Метод ->lastInsertId() всегда вызывается дескриптором базы данных (а не дескриптором состояния) и возвращает значение автоматически увеличивающегося идентификатора последней вставленной строки для данного соединения.

$DBH->exec("DELETE FROM folks WHERE 1"); $DBH->exec("SET time_zone = "-8:00"");

Метод ->exec() используется для различных вспомогательных операций.

$safe = $DBH->quote($unsafe);

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

$rows_affected = $STH->rowCount();

Метод ->rowCount() возвращает значение integer , указывающее количество строк, которые обрабатываются операцией. В последней версии PDO, в соответствии с отчетом об ошибках(http://bugs.php.net/40822) данный метод не работает с выражениями SELECT . Если у Вас возникли проблемы и Вы не можете обновить PHP, получить количество строк можно следующим способом:

$sql = "SELECT COUNT(*) FROM folks"; if ($STH = $DBH->query($sql)) { # Проверка количества строк if ($STH->fetchColumn() > 0) { # Здесь должен быть код SELECT } else { echo "Нет строк соответствующих запросу."; } }

Надеюсь, что урок Вам понравился!

На днях решил разобраться с php PDO. Это интересно и необходимо изучать новые технологии. Русской документации нигде не нашел, потому и решил выложить. Надеюсь эта статья будет Вам интересна.

Введение

Начнем сначала PHP Data Objects(PDO) – легкий интерфейс для доступа к базам данных в языке PHP. Он может работать с большинством баз данных, такими как MS SQL ,Firebird, MySQL , Oracle, PostgreSQL , SQLite и другими. Но тут необходимо обратить внимание, что PDO предоставляет необходимый функционал для работы с базами данных, но для каждого типа базы данных должен быть установлен свой драйвер доступа для базы данных в виде расширения PHP.

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

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

Формат вот такой:

тип_базы_данных:host=имя_хоста;db=name

Давайте рассмотрим на примере, только немного усложним пример, использованием исключений из библиотеки PDO (PDOException). Чтобы в случае неудачного подключения к базе данных, мы получили вразумительное сообщение об этом, а не кучу косяков коде, неизвестно откуда взявшихся.

try { $db = new PDO("mysql:host=localhost;dbname=test" , "root" , "" ) ; $rows = $db -> exec ("CREATE TABLE `testing`(id INT PRIMARY KEY AUTO_INCREMENT, fname VARCHAR(20) NOT NULL DEFAULT "", email VARCHAR(50) NOT NULL DEFAULT "")" ) ; } catch(PDOException $e ) { die ("Error: " . $e -> getMessage () ) ; }

Если же в SQL выражении вы допустили ошибку, в PDO есть специальные функции:

errorCode() – возвращает номер ошибки, и

errorInfo() – возвращает массив, в котором, как номер ошибки, так и текст описания

Запросы непосредственно можно делать двумя функциями:

exec() и query()

Отличие их состоит в типе возвращаемого результата, exec возвращает количество затронутых в результате выполнения запроса строк, а вторая, возвращает результат запроса в объекте PDOStatement, о нем поговорим чуть ниже.

Теперь добавим эти функции в код и сделаем пример чуть более сложным:

// в начале конфиг define ("DB_DRIVER" , "mysql" ) ; define ("DB_HOST" , "localhost" ) ; define ("DB_NAME" , "test" ) ; define ("DB_USER" , "root" ) ; define ("DB_PASS" , "" ) ; try { // соединяемся с базой данных $connect_str = DB_DRIVER . ":host=" . DB_HOST . ";dbname=" . DB_NAME; $db = new PDO($connect_str , DB_USER, DB_PASS) ; // вставляем несколько строк в таблицу из прошлого примера $rows = $db -> exec ("INSERT INTO `testing` VALUES (null, "Ivan", "[email protected]"), (null, "Petr", "[email protected]"), (null, "Vasiliy", "[email protected]") " ) ; $error_array = $db -> errorInfo () ; if ($db ->
" ; // если запрос был выполнен успешно, // то выведем количество затронутых строк if ($rows ) echo "Количество затронутых строк: " . $rows . "
" ; // теперь выберем несколько строчек из базы $result = $db -> query ("SELECT * FROM `testing` LIMIT 2" ) ; // в случае ошибки SQL выражения выведем сообщене об ошибке $error_array = $db -> errorInfo () ; if ($db -> errorCode () != 0000) echo "SQL ошибка: " . $error_array [ 2 ] . "

" ; // теперь получаем данные из класса PDOStatement while ($row = $result -> fetch () ) { // в результате получаем ассоциативный массив print_r ($row ) ; } } catch(PDOException $e ) { die ("Error: " . $e -> getMessage () ) ; }

Подготовленные выражения

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

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

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

И так для начала создадим подготовленное выражение, это делается функцией Prepare()

В качестве параметра она принимает SQL запрос, но в нем, вместо значений, которые необходимо менять, ставятся псевдо переменные, которые могут быть в виде знака вопроса(?), либо имени псевдо переменой, которое начинается с двоеточия (:)

$sth1 = $db->prepare(“SELECT * FROM `testing` WHERE id=:id”);

$sth2 = $db->prepare(“SELECT * FROM `testing` WHERE id=?”);

В зависимости от того, как вы определите переменную, будет зависеть ваша дальнейшая работа.

Если вы определили переменные знаком вопроса, то потом, в функцию execute передайте массив значений, в той, последовательности, в которой стоят переменные.

Если же вы обозначили переменные именами, то надо будет назначить каждой переменной значение посредством функций:

bindValue() – присваивает псевдопеременной значение

bindParam() – связывает псевдопеременную с настоящей переменной, и при изменении настоящей переменной, не нужно больше вызывать никаких дополнительных функций, можно сразу execute()

Вот пример использования первого варианта:


Обратите внимание, что после создания объектом PDO подготовленного выражения в классе PDOStatement, мы пользуемся только им, соответственно, в нем есть свои функции errorCode, errorInfo, а также результат выполнения запросов, также сразу же хранится в нем.

А теперь второй способ.

Для присваивания значения псевдо переменной, воспользуемся функцией bindValue()

Этот код можно записать еще проще, связав псевдопеременную с реальной:

Тут же необходимо добавить, что очень желательно (чтобы не возникало лишних ошибок) третьим параметром указывать тип переменной. У меня лично, в случае отсутствия типа переменной, возникали ошибки в операторе WHERE, так как он считал переменную текстом, а не числом.

$sth3->bindParam(‘:id’,$id, PDO::PARAM_INT);

$sth3->bindParam(‘:id’,$id, PDO::PARAM_STR);

Еще одним из очень приятных плюсов использования таких подготовленных выражений, это экранирование переменных. Перед подстановкой в процедуру все переменные экранируются и никакие SQL инъекции не страшны.

Транзакции

Транзакция – это совокупность запросов базу данных, которые должны быть обязательно выполнены все. Если какой-либо запрос не выполнен или выполнен с ошибкой, то транзакция отменяется и изменений данных в базе не происходит.

Это нужно, чтобы гарантировать сохранение целостности данных при нескольких запросах. например при переводе денежных средств со счета на счет.

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

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

Чтобы выключить режим автоподтверждения, выполняем команду:

$db->beginTransaction();

После этого выполняем столько запросов к базе данных сколько необходимо сделать в этой транзакции.

И только после того как все запросы будут выполнены, Вы можете подтвердить транзакцию функцией

$db->commit();

или отменить транзакцию

$db->rollback();

Вот небольшой пример транзакций:

try { $connect_str = DB_DRIVER . ":host=" . DB_HOST . ";dbname=" . DB_NAME; $db = new PDO($connect_str , DB_USER, DB_PASS) ; $rows = $db -> exec ("CREATE TABLE `testing`(id INT PRIMARY KEY AUTO_INCREMENT, fname VARCHAR(20) NOT NULL DEFAULT "", email VARCHAR(50) NOT NULL DEFAULT "", money INT NOT NULL DEFAULT 0) ENGINE=InnoDB;" ) ; $rows = $db -> exec ("INSERT INTO `testing` VALUES (null, "Ivan", "[email protected]", 15000), (null, "Petr", "[email protected]", 411000), (null, "Vasiliy", "[email protected]", 1500000) " ) ; // Попробуем от Ивана перевести сумму 50000 // Петру $summ = 50000 ; $transaction = true ; $db -> beginTransaction () ; $sth1 = $db -> query ("SELECT money FROM testing WHERE fname="Ivan"" ) ; $sth2 = $db -> query ("SELECT money FROM testing WHERE fname="Petr"" ) ; $row1 = $sth1 -> fetch () ; $row2 = $sth2 -> fetch () ; if (! $row1 || ! $row2 ) $transaction = false ; $total2 = $summ + $row2 [ "money" ] ; $total1 = $row1 [ "money" ] - $summ ; if ($total1 < 0 || $total2 < 0) $transaction = false ; $num_rows1 = $db -> exec ( . $total1 . "" WHERE fname="Ivan"" ) ; $num_rows2 = $db -> exec ("UPDATE `testing` SET money="" . $total2 . "" WHERE fname="Petr"" ) ; if ($transaction ) { echo "Транзакция успешно прошла" ; $db -> commit () ; } else { echo "Транзакция не прошла" ; $db -> rollback () ; } } catch(PDOException $e ) { die ("Error: " . $e -> getMessage () ) ; }

Тут еще следует заметить, что не все типы таблиц поддерживают транзакции, потому в этом примере я использовал таблицу InnoDb вместо стандартной MyISAM.

В заключении хотелось бы сказать, что это еще далеко не полный мануал по PDO. Всю самую свежую и полную информацию Вы всегда можете раздобыть вот здесь: http://www.php.net/manual/en/book.pdo.php

Изучайте и создавайте.

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

*Наведите курсор мыши для приостановки прокрутки.

Назад Вперед

Основы работы с расширением PDO

Сегодня мы с вами разберём очень интересную тему - основы работы с расширением PDO для PHP.

PDO (PHP Data Objects) - это просто некий интерфейс, который позволяет работать с различными базами данных без учета их специфики. С помощью PDO мы можем легко переключаться между разными базами данных и управлять ими. Чтобы стало понятнее, давайте разберём пример.

Как мы должны были подключаться раньше к базе MySQL ?

Mysql_connect($host, $user, $password); mysql_select_db($db);

Чтобы подключиться к SQLite мы должны были написать так:

Sqlite_open($db);

Если нам нужна база данных PostgreSQL , то надо написать так:

Pg_connect("host=$host, dbname=$db, user=$user, password=$password");

Не очень-то удобно, верно? Получается, что если мы захотим сменить базу данных, то нам придется переделывать много кода. И вот, чтобы это исправить, появилось специальное PHP-расширение - PDO .

Давайте посмотрим, как мы теперь можем подключиться к базе:

$db = new PDO("mysql:host=$host;dbname=$db", $user, $password);

$db = new PDO("sqlite:$db);

PostgreSQL:

$db = new PDO("pgsql:host=$host;dbname=$db", $user, $password);

Как видите, всё то же самое, кроме строки подключения. Это единственное различие.


Теперь давайте рассмотрим, как раньше мы были должны выполнять запросы:

$sql = "INSERT INTO(name, email) VALUES($name, $email)"; // MySQL mysql_query($sql); // SQLite sqlite_query($sql); // PostgreSQL pg_query($sql);

Теперь же мы можем абстрагироваться от этого:

// PDO $result = $db->exec($sql);

Всё! Наш запрос будет выполнен независимо от того, какую БД мы используем , а в переменную result попадёт количество затронутых строк.

Однако выбрать что-то из базы данных таким способом мы не сможем. Для выборки нам нужно использовать не exec , а query .

$sql = "SELECT name FROM users"; $result = $db->query($sql);

Теперь давайте вспомним и о безопасности , ведь все данные нужно проверять. Как мы делали это раньше?

$sql = "SELECT * FROM users WHERE name = $name"; $name = $_POST["name"]; // MySQL $name = mysql_real_escape_string($name); // SQLite $name = sqlite_escape_string($name); // PostgreSQL $name = pg_escape_string($name);

Теперь же нам не нужно этого делать. PDO сделает всё за нас.

$name = $db->quote($name); $result = $db->query($sql);

PDO сам всё проверит и обработает переданные данные. Круто?:) Дальше ещё круче! Продолжим.

Как мы раньше преобразовывали результат в массив? Рассмотрим на примере базы MySQL .

$result = mysql_query($sql); // Так $row = mysql_fetch_assoc($result); // Или так... $row = mysql_fetch_array($result, FETCH_ASSOC);

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

$stmt = $db->query($sql); // Ассоциативный $result = $stmt->FETCH(PDO::FETCH_ASSOC); // Нумерованный $result = $stmt->FETCH(PDO::FETCH_NUM); // Оба типа массивов одновременно $result = $stmt->FETCH(PDO::FETCH_BOTH); // Объект $result = $stmt->FETCH(PDO::FETCH_OBJ);

Использовать это также очень просто:

// Ассоциативный echo $result["name"]; // Нумерованный echo $result; // Объект echo $result->name;

Для "ленивых" есть такая вещь:

$stmt = $db->query($sql); $result = $stmt->FETCH(PDO::FETCH_LAZY);

Он возвращает сразу все 3 типа. Т.е. это FETCH_BOTH и FETCH_OBJ вместе. Как вы уже догадались, после этого доступ к данным можно получить любым из трех способов:

Echo $result->name; echo $result["name"]; echo $result;

Однако Fetch возвращает только одну запись, поэтому, если мы хотим получить все записи, то надо использовать FetchAll .

$stmt = $db->query("SELECT * FROM users"); $result = $stmt->FetchAll(PDO::FETCH_ASSOC); foreach($result as $user) { echo $user["name"]."
"; }

Но есть ещё одна классная штука, связанная с Fetch . С ее помощью мы можем заполнить наш класс данными из БД автоматически .

Class User { public $login; public $id; public function showInfo() { echo "".$this->id.""." : ".$this->login."
"; } } $db = new PDO("mysql:host=localhost;dbname=test", "root", ""); $stmt = $db->query("SELECT * FROM `users`"); $result = $stmt->fetchAll(PDO::FETCH_CLASS, "User"); foreach($result as $user) { $user->showInfo(); }

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

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

Помимо всего прочего, мы можем создавать так называемые подготовленные запросы . В чём их плюсы?

1. Мы можем один раз подготовить запрос, после чего запускать его столько раз, сколько нам нужно. Причём как с такими же, так и с другими параметрами.

Когда запрос подготовлен, СУБД анализирует его, компилирует и оптимизирует план его выполнения. В случае сложных запросов, время на выполнение будет ощутимо, если мы запускаем его с разными параметрами. В случае с подготовленными запросами это делается один раз и, следовательно, времени тратится меньше.

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

PDO может эмулировать подготовленные запросы , если они не поддерживаются драйвером. Теперь, давайте рассмотрим, как же их использовать?

$stmt = $db->prepare("INSERT INTO users (name, login) VALUES (:name, :login)"); $stmt->bindParam(":name", $name); $stmt->bindParam(":login", $login); // Вставим одну строку с такими значениями $name = "vasya"; $login = "vasya123"; $stmt->execute(); // Теперь другую строку с другими значениями $name = "petya"; $login = "petya123"; $stmt->execute();

Метод bindParam позволяет нам установить параметры. Думаю, тут всё понятно. Сначала там, где хотим, чтобы были вставлены данные, пишем такую строчку ":имя ". А затем указываем, откуда они будут браться. В данном случае они будут браться из переменных name и login .

Теперь мы можем использовать этот запрос с разными параметрами сколько угодно раз, а чтобы его выполнить, нужно вызвать метод execute . Это были именованные параметры. Также есть и не именованные .

$stmt = $db->prepare("INSERT INTO users (name, login) VALUES (?, ?)"); // Данные из переменной name будут вставлены вместо первого знака вопроса $stmt->bindParam(1, $name); // Данные из переменной login будут вставлены вместо второго знака вопроса $stmt->bindParam(2, $login); // Вставим одну строку с такими значениями $name = "vasya"; $login = "vasya123"; $stmt->execute(); // Теперь другую строку с другими значениями $name = "petya"; $login = "petya123"; $stmt->execute();

Следующий момент - как нам отлавливать ошибки?

Для этого есть класс PDOException . Я рекомендую все ваши запросы писать в блоке try-catch .

Try { $db = new PDO("myql:host=localhost;dbname=test", "root", ""); $stmt = $db->query("SELECT * FROM users"); $result = $stmt->fetch(PDO::FETCH_ASSOC); echo $result["login"]; } catch(PDOException $e) { echo "Ошибка: ".$e->getMessage()."
"; echo "На линии: ".$e->getLine(); }

Здесь мы допустили ошибку и написали myql вместо mysql . И класс PDOException нам об этом напишет.

У него несколько методов, но самые часто используемые это getMessage() , который возвращает нам текст ошибки и getLine() , который возвращает номер строки, на которой допущена ошибка.

Ну и напоследок поговорим о транзакциях . Сначала приведу код.

Try { $db = new PDO("mysql:host=localhost;dbname=test", "root", ""); $db->beginTransaction(); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login1")"); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login2")"); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login3")"); $db->commit(); } catch(PDOException $e) { $db->rollBack(); }

Здесь мы начинаем транзакцию с помощью метода beginTransaction() . Дальше идёт какой-то код запросов. Затем мы вызываем метод commit() , чтобы подтвердить наши изменения. Если же что-то пошло не так, то в блоке catch мы вызываем метод rollBack() , который вернёт все наши данные в предыдущее состояние.

"А зачем собственно нужны эти транзакции?" - спросите вы. Чтобы ответить на этот вопрос, рассмотрим пример, который я привёл выше. Там вы вставляем в поле "логин" значение login1, login2, login3 .

Представим, что после того, как вставились login1 и login2 , произошла какая-то ошибка. Получится, что эти данные вставлены, а login3 - нет. Во многих случаях это недопустимо и нарушит работу приложения в будущем.

Как раз для предотвращения таких ситуаций и нужны транзакции. Если наш скрипт дал сбой, то метод rollBack() вернёт всё в первоначальный вид. Т.е. login1 и login2 также не будут вставлены. Давайте сэмулируем эту ошибку.

Try { $db = new PDO("mysql:host=localhost;dbname=test", "root", ""); $db->beginTransaction(); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login1")"); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login2")"); exit("error"); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login3")"); $db->commit(); } catch(PDOException $e) { $db->rollBack(); }

После вставки login1 и login2 мы выходим из скрипта с помощью функции exit() . У нас выбрасывается исключение, мы попадаем в блок catch , а там мы возвращаем всё в первоначальный вид. Теперь, если мы посмотрим в базу данных, то не увидим там login1 и login2 .

На этом моменте мы закончим. Очевидно, что здесь мы разобрали далеко не всё, что предоставляет нам PDO, однако узнали основы работы с ним. Более подробную информацию о данном расширении вы всегда можете найти на официальном сайте PHP.

Материал подготовил Владислав Андреев специально для сайта сайт

P.S. Хотите двигаться дальше в освоении PHP и ООП? Обратите внимание на премиум-уроки по различным аспектам сайтостроения, включая программирование на PHP, а также на бесплатный курс по созданию своей CMS-системы на PHP с нуля с использованием ООП:

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


PDO (PHP Data Objects) - расширение для PHP, предоставляющее простой интерфейс для доступа к различным базам данных. Если говорить очень просто и коротко, при помощи PDO в PHP подключаются к базам данных разных типов.

В этом уроке мы будем подключаться к базе данных MySQL, так как это самая распространённая база данных.

Подключение к базе данных

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

Пример того, как мы можем подключиться к базе данных:

$db = new PDO("mysql:host=$host;dbname=$db", $user, $pass);

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

Итак, у нас есть объект подключения для доступа к базе данных.

Обработка исключений

Когда используется PDO, то ошибки подключений советуюю ловить при помощи конструкции try{...}catch{...} . Вот пример такого кода:

Try { $db = new PDO("myql:host=$host;dbname=$dbname", $user, $pass); } catch(PDOException $e) { echo "You have an error: ".$e->getMessage()."
"; echo "On line: ".$e->getLine(); }

Есть разные мнения, по поводу обработки ошибок, например не все советуют всегда использовать конструкцию try{...}catch{...} . Дело в том, что PHP и так выведет сообщение об ошибке на экран, так что этот код избыточен. Хотя если вы хотите например откатить транзакцию, то эта конструкция вам пригодится, но об этом ниже.

Получение данных из базы используя PDO, метод query

Для выборки из базы данных используется метод query , которому мы передаём строку запроса SQL.

$db->query("SELECT * FROM users");

Не забывайте, что для всех типов баз данных этот синтаксис сработает.

Также не забывайте про безопасность данных, передаваемых в SQL запросах. В PDO есть аналог функции mysql_real_escape_string() это метод quote .

$login = $db->quote($_POST["login"]); $sql = "SELECT * FROM users WHERE login = $login"; $result = $db->query($sql);

Обработка результата, методы FETCH и FETCHALL.

Теперь нам нужно преобразовать результат из переменной $res в массив. Это делается при помощи метода FETCH , которому передаётся константа.

$res = $db->query($sql); $result = $res->FETCH(PDO::FETCH_NUM); // нумерованный $result = $res->FETCH(PDO::FETCH_ASSOC); // ассоциативный $result = $res->FETCH(PDO::FETCH_BOTH); // ассоциативный и нумерованный вместе $result = $res->FETCH(PDO::FETCH_OBJ); // объектный тип $result = $res->FETCH(PDO::FETCH_LAZY); // сразу все типы

Очевидно, что константа FETCH_LAZY замедляет работу скрипта, поэтому её желательно не использовать.

Метод FETCH возвращает одну запись из результата. Если требуется получить все записи, нужно использовать метод FETCHALL . В дальнейшем результат, полученный в результате использования FETCHALL обрабаьываем в цикле foreach , как показано в примере:

$query = $db->query("SELECT * FROM users"); $result = $query->FETCHALL(PDO::FETCH_ASSOC); foreach($result as $arry) { echo $arry["name"] . "
"; }

Константа FETCH_CLASS

Особого объяснения требует константа FETCH_CLASS , она позволяет заполнить предварительно созданный класс данными из результата запроса к базе данных.

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

Class User { public $login; public $pass; public function showInfo() { echo "
" . $this->pass."
" . " : " . $this->login . "
"; } } $result = $stmt->FETCHALL(PDO::FETCH_CLASS, "User"); foreach($result as $user) { $user->showInfo(); }

Не забывайте важное правило - названия свойств в созданном классе обязаны быть такими же, как и названия полей в базе данных.

Подготовленные выражения

Подготовленные выражения нужно обязательно использовать если ваш SQL запрос содержит переменные.

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

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

Именнованные плейсхолдеры

Сначала давайте рассмотрим именнованный плейсхолдер, его синтаксис например такой: :email .

Давайте рассмотрим пример запроса INSERT с использованием плейсхолдеров.

$stmt = $db->prepare("INSERT INTO messages (email, message) VALUES (:email, :message)");

В этом примере вместо переменных в запросе мы использовали два плейсхолдера (:email, :message)") .

$stmt = $db->prepare("INSERT INTO messages (email, message) VALUES (:email, :message)"); $stmt->bindParam(":email", $email); $stmt->bindParam(":message", message); $email = "Е-почта №1"; $message = "Какой-то текст сообщения"; $stmt->execute(); $email = "Е-почта №2"; $message = "Какой-то текст сообщения"; $stmt->execute();

Обратите внимание, что чтобы подготовить SQL запрос, мы пишем его в методе prepare() . Потом, чтобы указать к какому плейсхолдеру какую переменную привязать, используем метод bindParam() . Чтобы выполнить SQL запрос, мы вызываем метод execute() .

Итак, ещё раз последовательность работы с подготовленными выражениями по шагам:

  • Присваиваем переменной $stmt результат выполнения метода prepare() .
  • При помощи метода bindParam() мы связываем переменные и плейсхолдеры.
  • Назначаем значения переменных.
  • При помощи метода execute() выполняем запрос к базе данных.
  • Этот синтаксис можно записать

    $stmt = prepare("SELECT name FROM users WHERE email = :email"); $stmt->execute(array("email" => $email));

    Видно, что в метод execute() должен передаваться массив, в котором ключи должны совпадать с именами плейсхолдеров.

    Кстати, у метода bindParam() есть синоним bindValue() .

    Неименованные плейсхолдеры

    Теперь рассмотрим работу с неименованными плейсхолдерами.

    $stmt = prepare("SELECT name FROM users WHERE email = ?") $stmt->execute(array($email));

    В этом синтаксисе вместо записи плейсхолдера:название указывается другая форма его записи - знак вопроса:? .

    Тут значения массива $email будут поочерёдно присвоены плейсхолдерам:? , но в нашем примере плейсхолдер один.

    Вот другой пример применения неименованных плейсхолдеров, с использованием метода bindParam() :

    $stmt = $db->prepare("INSERT INTO articles (title, text) VALUES (?, ?)"); $stmt->bindParam(1, $email); $stmt->bindParam(2, $message); $email = "Е-почта №1"; $message = "Какой-то текст сообщения"; $stmt->execute(); $email = "Е-почта №2"; $message = "Какой-то текст сообщения"; $stmt->execute();

    Вставка в базу данных, метод exec()

    Если мы хотим что-нибудь записать в базу, тогда можно также использовать метод PDO::exec() .

    $sql = "INSERT INTO (login, password) VALUES ($login, $password)"; $result = $db->exec($sql);

    Если этот запрос будет выполнен, то в переменную $result попадёт количество затронутых в таблице строк.

    PDO::exec() выполняет INSERT запросы, но не может получить данные из БД, этим занимается метод PDO::query() . PDO::exec() только запускает SQL запрос на выполнение и возвращает количество строк, задействованных в ходе его выполнения, он не возвращает результат выборки оператором SELECT .

    PDO работает с базами данных. Если с каким-то типом базы данных не получается работать, идём в php.ini и ищем строчки начинающиеся с extension=php_pdo_{название базы данных}, и раскомментируем их.

    Php для начинающих: Callback функции, урок 34! https://www.youtube.com/watch?v=2NwLHXUoXcw https://www.youtube.com/watch?v=GMzI6jR_bE4 https://www.youtube.com/watch?v=gFJsBQIqpto PHP урок 9 Рекурсия https://www.youtube.com/watch?v=gLAeJcKkd6c http://php.net/manual/ru/mysqli-result.fetch-array.php /* очищаем результаты выборки */ mysqli_free_result($result); /* закрываем подключение */ mysqli_close($link); http://myrusakov.ru/sql-osnovy.html Хорошая статья: https://ru.wikipedia.org/wiki/Join_(SQL) ООП PHP. Расширительные средства Глава "Расширительные средства" из книги Мэта Зандстра "PHP. Объекты, шаблоны и методики программирования". https://www.youtube.com/watch?v=6L2bxtTBCRo

    http://phpfaq.ru/pdo#intro - тут хорошая статья. Есть про исключения важная информация.

    Проще описано: http://myrusakov.ru/php-data-objects.html

    Video: https://www.youtube.com/watch?v=ACUiBH5qV0U&list=PLr_acfJGVcirEijJXmKxj8QGkWkKb-Tj-&nohtml5=False

    Introduction

    Optionally, the --with-mysql-sock[=DIR] sets to location to the MySQL unix socket pointer for all MySQL extensions, including PDO_MYSQL. If unspecified, the default locations are searched.

    Optionally, the --with-zlib-dir[=DIR] is used to set the path to the libz install prefix.

    $ ./configure --with-pdo-mysql --with-mysql-sock=/var/mysql/mysql.sock

    Changelog Version Description
    5.4.0 mysqlnd became the default MySQL library when compiling PDO_MYSQL. Previously, libmysqlclient was the default MySQL library.
    5.4.0 MySQL client libraries 4.1 and below are no longer supported.
    5.3.9 Added SSL support with mysqlnd and OpenSSL.
    5.3.7 Added SSL support with libmysqlclient and OpenSSL.
    Predefined Constants

    The constants below are defined by this driver, and will only be available when the extension has been either compiled into PHP or dynamically loaded at runtime. In addition, these driver-specific constants should only be used if you are using this driver. Using driver-specific attributes with another driver may result in unexpected behaviour. PDO::getAttribute() may be used to obtain the PDO::ATTR_DRIVER_NAME attribute to check the driver, if your code can run against multiple drivers.

    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (integer ) If this attribute is set to TRUE on a PDOStatement , the MySQL driver will use the buffered versions of the MySQL API. If you"re writing portable code, you should use PDOStatement::fetchAll() instead.

    Example #1 Forcing queries to be buffered in mysql

    PDO::MYSQL_ATTR_LOCAL_INFILE (integer )

    Enable LOAD LOCAL INFILE .

    PDO::MYSQL_ATTR_INIT_COMMAND (integer )

    Command to execute when connecting to the MySQL server. Will automatically be re-executed when reconnecting.

    Note, this constant can only be used in the driver_options array when constructing a new database handle.

    PDO::MYSQL_ATTR_READ_DEFAULT_FILE (integer )

    Read options from the named option file instead of from my.cnf . This option is not available if mysqlnd is used, because mysqlnd does not read the mysql configuration files.

    PDO::MYSQL_ATTR_READ_DEFAULT_GROUP (integer )

    Read options from the named group from my.cnf or the file specified with MYSQL_READ_DEFAULT_FILE . This option is not available if mysqlnd is used, because mysqlnd does not read the mysql configuration files.

    PDO::MYSQL_ATTR_MAX_BUFFER_SIZE (integer )

    Maximum buffer size. Defaults to 1 MiB. This constant is not supported when compiled against mysqlnd.

    PDO::MYSQL_ATTR_DIRECT_QUERY (integer )

    Perform direct queries, don"t use prepared statements.

    PDO::MYSQL_ATTR_FOUND_ROWS (integer )

    Return the number of found (matched) rows, not the number of changed rows.

    PDO::MYSQL_ATTR_IGNORE_SPACE (integer )

    Permit spaces after function names. Makes all functions names reserved words.

    PDO::MYSQL_ATTR_COMPRESS (integer )

    Enable network communication compression. This is also supported when compiled against mysqlnd as of PHP 5.3.11.

    PDO::MYSQL_ATTR_SSL_CA (integer )

    The file path to the SSL certificate authority.

    This exists as of PHP 5.3.7.

    PDO::MYSQL_ATTR_SSL_CAPATH (integer )

    The file path to the directory that contains the trusted SSL CA certificates, which are stored in PEM format.

    This exists as of PHP 5.3.7.

    PDO::MYSQL_ATTR_SSL_CERT (integer )

    The file path to the SSL certificate.

    This exists as of PHP 5.3.7.

    PDO::MYSQL_ATTR_SSL_CIPHER (integer )

    A list of one or more permissible ciphers to use for SSL encryption, in a format understood by OpenSSL. For example: DHE-RSA-AES256-SHA:AES128-SHA

    This exists as of PHP 5.3.7.

    PDO::MYSQL_ATTR_SSL_KEY (integer )

    The file path to the SSL key.

    This exists as of PHP 5.3.7.

    PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT (integer )

    Provides a way to disable verification of the server SSL certificate.

    This exists as of PHP 7.0.18 and PHP 7.1.4.

    PDO::MYSQL_ATTR_MULTI_STATEMENTS (integer )

    Disables multi query execution in both PDO::prepare() and PDO::query() when set to FALSE .

    Note, this constant can only be used in the driver_options array when constructing a new database handle.

    This exists as of PHP 5.5.21 and PHP 5.6.5.

    Runtime Configuration

    The behaviour of these functions is affected by settings in php.ini .

    PDO_MYSQL Configuration Options Name Default Changeable
    pdo_mysql.default_socket "/tmp/mysql.sock" PHP_INI_SYSTEM
    pdo_mysql.debug NULL PHP_INI_SYSTEM
    For further details and definitions of the PHP_INI_* modes, see the .

    Here"s a short explanation of the configuration directives.

    Sets a Unix domain socket. This value can either be set at compile time if a domain socket is found at configure. This ini setting is Unix only.

    Pdo_mysql.debug boolean

    Enables debugging for PDO_MYSQL. This setting is only available when PDO_MYSQL is compiled against mysqlnd and in PDO debug mode.

    Table of Contents
    • PDO_MYSQL DSN - Connecting to MySQL databases

    Than install them

    rpm -Uvh remi-release-26.rpm
    rpm -Uvh epel-release-6-8.noarch.rpm

    Know you can use remi repository to gest php-pdo and php-mysql.

    yum --enablerepo=remi install php-pdo
    yum --enablerepo=remi install php-mysql

    Restart the Apache

    systemctl stop httpd
    systemctl start httpd

    Good to go!

    10 years ago

    SQLSTATE: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

    This one can be a royal pain to deal with. Never stack statements to be executed in one go. Nobody ever mentions this possibility in all the posts I"ve seen dealing with this error.

    This example is a Zend Framework example but the theory is the same.


    This will run fine but PDO will balk with the "unbuffered" error if you follow this with another query.


    Chopping it into individual queries fixes the problem.