Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк 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.

Хостинг

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

MySQL:


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

SQLite:


$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[0];

// Объект
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[0];

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

Хостинг


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

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


class User {

public $login;
public $id;

    public function showInfo() {
	    echo "<b>".$this->id."</b>"." : ".$this->login."<br>";
    }
}

$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()."<br>";
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.

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

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

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


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх