PDO для новичков

Статью писал для своего сайта, но по некоторым причинам решил все свои статьи перезалить сюда! (что бы не утерять)

В следствии новости от разработчиков php, о прекращении поддержки расширения MySQL в PHP, в массах начинающих разработчиков (пишущих свои творения на языке php) началась паника.
Для паники пока что нет поводов, полностью расширение планируют убрать в шестой ветке php, которая выйдет еще не скоро! а пока что: "По*** пляшем"! так что есть время хорошенько изучить PDO или MySQLi. Лично я советую PDO.

И так! Для начала хотелось бы указать какие методы нам понадобятся для работы с PDO:

Основной класс PDO:
PDO :: BeginTransaction - Начало транзакции.
PDO :: commit - Выполнить транзакцию.
PDO :: exec - Выполнить SQL выражения и возвращение количество задействованных рядов.
PDO :: lastInsertId - Возвращает идентификатор последней вставленной строки или последовательности значения.
PDO :: prepare - Готовит оператор для выполнения и возвращает объект оператора.
PDO :: query - Выполняет SQL запрос.
PDO :: quote - Экранирование спец символов для использования в запросе.

Представление подготовленных заявлений PDOStatement:
PDOStatement -> execute - Выполнение подготовленного заявления.
PDOStatement -> fetch - Выбирает следующую строку из результирующего набора.
PDOStatement -> fetchAll - Возвращает массив, содержащий все строки результирующего набора.
PDOStatement -> fetchColumn - Возвращает один столбец из следующей строки результирующего набора.

Это далеко не весь набор методов для работы с PDO, полный список вы можете посмотреть тут http://php.net/manual/en/book.pdo.php

Первое что нам необходимо, это подключится к базе данных:
<?php
/* Сервер на котором расположена база данных. */
$dsn  = 'host=localhost;';
/* Имя базы данных с которой работаем. */
$dsn .= 'dbname=testbase;';
* Номер порта локального сервера. */
$dsn .= 'dbport=3306;';

/* Указываем кодировку с которой работаем. */
$driver = array(PDO :: MYSQL_ATTR_INIT_COMMAND => 'SET NAMES `utf8`');

try {
    $dbh = new PDO($dsn, $login, $passwd, $driver);
} catch (PDOException $e) {
    echo $e -> getMessage();
}
?>
Начиная с PHP 5.3.6 можно указывать кодировку в конструкторе:
<?php
/* Сервер на котором расположена база данных. */
$dsn  = 'host=localhost;';
/* Имя базы данных с которой работаем. */
$dsn .= 'dbname=testbase;';
* Номер порта локального сервера. */
$dsn .= 'dbport=3306;';
* Указываем кодировку. */
$dsn .= 'charset=utf8;';

try {
    $dbh = new PDO($dsn, $login, $passwd);
} catch (PDOException $e) {
    echo $e -> getMessage();
}
?>
Теперь мы подключились, и можем работать с запросами!
Первое что нам понадобится, это добавление записей в базу данных:
<?php
$dbh -> exec("INSERT INTO `table` (`pole`) VALUES ('value');");

/* И сразу о применении lastInsertId() 
 * После добавления записи можно узнать id строки,
 * которую вы только что добавили.
 */
echo $dbh ->lastInsertId();
?>
А так же о пользе транзакций:

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

Например нам необходимо выполнить INSERT INTO и UPDATE:

<?php
$dbh -> exec("INSERT INTO `privat` (`login`, `text`) VALUES ('Nu3oN', 'Hello');");
$dbh -> exec("UPDATE `users` SET `privat` = `privat` + 1 WHERE `user` = 'Nu3oN';");
?>
И как видим, если первый запрос не выполнится, то у пользователя все равно покажет что у него еще одно сообщение, хотя его не самом деле нет. Данный пример конечно не лучший, для показания плюса транзакций, но для обучения самое оно. Что бы не произошло такой ошибки, можно воспользоваться транзакциями:

<?php
try {
    $dbh -> beginTransaction();

    $dbh -> exec("INSERT INTO `privat` (`login`, `text`) VALUES ('Nu3oN', 'Hello');");
    $dbh -> exec("UPDATE `users` SET `privat` = `privat` + 1 WHERE `user` = 'Nu3oN';");

    $dbhh -> commit();
} catch(PDOException $e) {
    echo 'Ошибка при добавлении сообщения';
}
?>
Теперь получение информации:
<?php
// Непосредственно сам запрос:

$res = $dbh -> query("SELECT * FROM `table`;");

// Возможные способы представления информации:

/* Массив с числовыми ключами. */
$row = $res -> fetch(PDO :: FETCH_NUM);
/* Массив с ключами используемыми в названиях столбцов. */
$row = $res -> fetch(PDO :: FETCH_ASSOC);
/* Массив содержащий все строки в пределах запроса. */
$row = $res -> fetchAll(PDO :: FETCH_ASSOC);

/// Это можно использовать в циклах например.
while ($row = $res -> fetch(PDO :: FETCH_ASSOC)) {
    echo $row['pole'];
}

/// В примере с fetchAll можно так:
foreach ($row as $arr) {
    echo $arr['pole'];
}

// Выбор одной строки:

$res = $dbh -> query("SELECT `id` FROM `table` WHERE `pole` = 'value';");
$str = $res -> fetchColumn();
?>
В этом думаю ничего сложного нет...
Теперь я бы хотел рассказать о возможности запросов с подготовленным выполнением (prepare и execute):

Возможности запросов с заранее подготовленным выполнением:
- компилируется один раз, выполняется необходимое количество раз.
- четкое разделение между структурой и входными данными (предотвращение SQL инъекция).
- быстрое выполнение по сравнению с query()/exec(), даже для единичного выполнения.

Пример запроса:
<?php
$array = array(
               $_GET['value1'], 
               $_GET['value2']
              );

$stmt  = $dbh -> prepare("SELECT * FROM `table` WHERE `pole` = ? AND `pole2` = ?;");
$stmt -> execute($array);
$arr = $stmt-> fetchAll(PDO :: FETCH_ASSOC);
?>
Параметры для запроса могут быть даны в виде имен и быть привязаны к переменным:

<?php
$array = array(
               ':value'  => $_GET['value1'], 
               ':value2' => $_GET['value2']
              );

$stmt -> prepare('SELECT * FROM `table` WHERE `pole` = :value AND `pole2` = :value2;');
$stmt -> execute($array);
$arr = $stmt -> fetchAll(PDO :: FETCH_ASSOC);
?>
И на последок, для того что бы не писать каждый раз в таких методах как fetch() и fetchAll() способ извлечения (PDO :: FETCH_ASSOC, PDO :: FETCH_NUM и прочие), можно после подключения к базе указать способ по умолчанию PDO :: FETCH_ASSOC, а потом по необходимости уже указывать способы которые вам необходимы!

Например:
<?php
try {
    $dbh = new PDO($dsn, $login, $passwd, $driver);
    $dbh -> setAttribute(PDO :: ATTR_DEFAULT_FETCH_MODE, PDO :: FETCH_ASSOC);
} catch (PDOException $e) {
    echo $e -> getMessage();
}
?>
Спасибо за внимание, если что не понятно спрашивайте!
Статья подготовлена специально для http://www.7je.ru

URL: https://visavi.net/articles/363