От автора: при создании собственных сайтов или CMS на языке PHP, так или иначе, необходимо использовать базу данных для хранения контента, и зачастую разработчики используют для этого систему управления базами данных MySQL. Долгое время, для работы с вышеуказанной СУБД использовалось одноименное расширение языка PHP – mysql, которое очень хорошо справлялось со своей задачей, но как говорится, ни что не вечно, и с выходом PHP 5.5, данное расширение было объявлено устаревшим. Поэтому в данном небольшом уроке я хотел бы поговорить о расширении PDO, которое предлагает универсальный способ работы с различными базами данных.
Итак, PDO – PHP Data Objects – это библиотека, которая содержит набор методов, по работе с различными базами данных, при этом доступ к конкретной базе данных, осуществляется при помощи соответствующего драйвера, который обязательно должен быть подключен в интерпретаторе языка PHP, Таким образом PDO, обеспечивает абстракцию доступа к базам данным, а это значит, что независимо от того, какая база используется, для работы с данными, Вы можете использовать одни и те же методы. Что очень удобно для реализации поддержки в создаваемом скрипте различных баз данных.
PDO предлагает только объектно-ориентированных подход и внедрен в язык PHP, начиная с версии 5.1.
Начало работы
Для начала, необходимо убедиться, что драйвер расширения PDO, для интересующей базы данных подключен в Вашем интерпретаторе языке PHP. Для этого открываем главный конфигурационный файл php.ini, который содержится в корне директории, в которую установлен интерпретатор. Далее опускаемся в блок подключаемых расширений, и убираем точку с запятой перед стройкой интересующего драйвера. К примеру, если, PDO, будет использоваться для работы с СУБД MySQL, значит необходимо убедиться, что подключено расширение php_pdo_mysql.dll.
Для СУБД SqLite — php_pdo_sqlite.dll. В данное время PDO PHP поддерживает 12 различных СУБД, полный список которых приведен на странице официальной документации.
Если интересующее расширение закомментировано, то есть перед строкой драйвера указана точка с запятой, значит, необходимо ее удалить и перезапустить веб-сервер Apache. Теперь можно приступать к работе с PDO.
Подключение к базе данных
Для подключения к интересующей базе данных, необходимо создать объект глобального класса PDO, и передать определенные параметры методу конструктору. Для подключения к базе данных MySQL (PDO MySQL), необходимо указать следующее:
1 |
$pdo = new PDO('mysql:host=localhost;dbname=slim_db;charset=utf8','root',''); |
В качестве первого параметра, в конструктор класса PDO, передается специальная строка, которая содержит в себе тип базы данных (имя драйвера), далее путь к серверу базы данных (через двоеточие), имя базы данных, к которой будет выполнено подключение и кодировка. При этом специальная строка с информацией подключения, для каждого драйвера своя, и более подробно о каждом драйвере можно почитать в документации.
Второй параметр – это имя пользователя для подключения к базе данных. Третий и последний параметр – пароль доступа к базе данных. Для работы с базой данных SqLite, при создании объекта PDO, следует передать следующие параметры:
1 |
$pdo = new PDO('sqlite:example.db'); |
База данных SqLite, обычно располагается в единственном файле, поэтому конструктору класса PDO, достаточно передать всего один параметр, с указанием имени драйвера и имени файла с базой данных.
И последний пример – для соединения с СУБД MsSQL, необходимо прописать следующее:
1 |
$pdo = new PDO("mssql:host=$host;dbname=$dbname", $user, $pass); |
Для обработки исключений, код можно заключить в блок try, и соответственно в блоке catch(), выполнять необходимые действия, при возникновении ошибок:
1 2 3 4 5 6 7 |
try { $pdo = new PDO('mysql:host=localhost;dbname=slim_db;charset=utf8','root',''); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { echo $e->getMessage(); } |
При этом в PDO предусмотрен специальный класс для работы с исключениями PDOException, который, конечно же, мы и используем. Используя метод setAttribute(), указываем режим обработки ошибок – константа PDO::ERRMODE_EXCEPTION. Это наилучший режим, на этапе разработки кода. То есть при возникновении ошибки, будет сгенерировано исключение, которое будет обработано в блоке catch().
Выборка данных
Теперь давайте поговорим о том, как же выполнить выборку данных из определенной таблицы базы данных. Для выполнения запроса, который должен вернуть некий результат, то есть запрос типа SELECT, в классе PDO предусмотрен метод query():
1 2 3 4 5 6 |
$sql = "SELECT * FROM slim_users"; $result = $pdo->query($sql); foreach($result as $row) { echo "<p>".$row['id']." | ".$row['username']; } |
Обратите внимание, что вызывая метод query(), в качестве первого параметра передается запрос, который необходимо выполнить. При этом возвращается объект класса PDOStatement, который можно использовать для получения готового результат. А именно, используя цикл foreach(), пройтись по данному объекту, как по обычному много-мерному ассоциативному массиву и отобразить данные на экран в требуемом виде.
Также для чтения результатов можно использовать метод fetch(), который извлекает следующую строку из результирующего набора.
1 2 3 4 5 |
$sql = "SELECT * FROM slim_users"; $result = $pdo->query($sql); while($row = $result->fetch()) { echo "<p>".$row['id']." | ".$row['username'];} |
В качестве первого параметры при вызове метода fetch(), передается режим работы данного метода, то есть, в каком виде будут возвращаться данные. Режим работы – это одна из следующих констант
PDO::FETCH_ASSOС — возвращает ассоциативный массив, в котором имена ячеек, совпадают с именами выбранных полей.
1 2 3 |
while($row = $result->fetch(PDO::FETCH_ASSOC)) { echo "<p>".$row['id']." | ".$row['username']; } |
PDO::FETCH_NUM — возвращает простой индексный массив.
1 2 3 |
while($row = $result->fetch(PDO::FETCH_NUM)) { echo "<p>".$row[0]." | ".$row[1]; } |
PDO::FETCH_BOTH возвращает как индексный массив, так и ассоциативный.
1 2 3 |
while($row = $result->fetch(PDO::FETCH_BOTH)) { echo "<p>".$row[0]." | ".$row['username']; } |
PDO::FETCH_OBJ – возвращает массив объектов, имена свойств которых совпадают с именами выбранных столбцов.
1 2 3 |
while($row = $result->fetch(PDO::FETCH_OBJ)) { echo "<p>".$row->getId()." | ".$row->getUsername(); } |
PDO::FETCH_CLASS: создает и возвращает объект определенного класса, присваивая значения столбцов результирующего набора, именованным свойствам класса. При этом данную константу передают в качестве первого параметра методу setFetchMode(), а в качестве второго — имя класса. К примеру, создадим класс, имена свойств, которого совпадает с именами выбранных столбцов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php class User { protected $id; protected $username; public function getId() { return $this->id; } public function getUsername() { return $this->username; } } |
Теперь, используем его для получения данных выборки:
1 2 3 4 5 6 7 |
$sql = "SELECT * FROM slim_users"; $result = $pdo->query($sql); $result->setFetchMode(PDO::FETCH_CLASS,'User'); while($row = $result->fetch()) { echo "<p>".$row->getId()." | ".$row->getUsername(); } |
То есть в методах данного класса, можно указать некоторые действия, которые будут обрабатывать выбираемые данные. При этом метод setFetchMode(), указывает режим работы метода fetch() и метода fetchAll(). Для получения всех строк результирующего набора, можно использовать метод fetchAll(), который за один вызов, вернет абсолютно все выбранные данные, что очень удобно:
1 2 3 4 5 |
$sql = "SELECT * FROM slim_users"; $result = $pdo->query($sql); $result->setFetchMode(PDO::FETCH_ASSOC); print_r($result->fetchAll()); |
Вставка и обновление данных
Для выполнения запросов, типа INSERT и UPDATE, необходимо вызвать метод exec() и в качестве первого параметра, передать выполняемый SQL запрос. При этом данный метод вернет количество задействованных строк в ходе выполнения запроса.
1 2 3 |
$sql = 'INSERT INTO `slim_users` (`username`, `password`) VALUES ("newsuser","newpassword")'; $affacted_rows = $pdo->exec($sql); echo $affected_rows; |
Подготовленные выражения
Расширение PDO, в отличие от устаревшего mysql, поддерживает подготовленные выражения. Подготовленный SQL запрос – это заранее скомпилированный SQL запрос, который может быть выполнен многократно. Подготовленные выражения более безопасны, так как не проходят SQL-инъекции и быстрее стандартных запросов. Рассмотрим следующее SQL выражение:
1 |
$sql = "SELECT * FROM slim_users WHERE `id` = :id"; |
На первый взгляд – это обычный SQL запрос, но вместо значения в условии WHERE, указывает так называемый “placeholder”, то есть ячейка для будущего значения. Само же значение будет передано, во время выполнения запроса — после его подготовки. При этом в SQL запросе, я использовал именованный “placeholder” (имя указывается после двоеточия). Для подготовки и выполнения данного запроса используем следующий код:
1 2 3 |
$result = $pdo->prepare($sql); $id = 1; $result->execute(array(':id' => $id)); |
То есть метод prepare(), подготавливает SQL выражение, а метод execute() – его выполняет. При этом в качестве первого параметра, при вызове метода execute(), передается значение для “placeholder” (проставленной метки в SQL выражении). Формируя SQL запрос, можно использовать неименованные параметры:
1 2 3 4 |
$sql = "SELECT * FROM slim_users WHERE `id` = ?"; $result = $pdo->prepare($sql); $id = 3; $result->execute(array($id)); |
Так же передаваемые значения в SQL выражение, можно привязать к определенным переменным, используя метод bindParam():
1 2 3 4 5 |
$sql = "SELECT * FROM slim_users WHERE `id` = :id"; $result = $pdo->prepare($sql); $id = 3; $result->bindParam(':id',$id,PDO::PARAM_INT); $result->execute(); |
При вызове метода bindParam(), в качестве первого параметра, передается имя “placeholder”, в качестве второго – переменная, к которой привязывается параметр запроса, а третьим параметром передается тип данных значения параметра, который задан одной из стандартных констант. Полный список констант, можно увидеть на странице документации.
На этом данный урок завершен. Мы с Вами рассмотрели только основы расширения PDO, поэтому если Вас заинтересовало данное расширение, в официальной документации, Вы найдете более расширенную информацию.
Всего Вам доброго и удачного кодирования!!!
Комментарии (4)