Для начала, скажу что статья рассчитана на программистов,
имеющих опыт работы с СУБД, а не на начинающих пхпешников. Я
предполагаю, что вы знакомы с PHP, ОПП, SQL и имеете опыт
разработки web-приложений.
ADODB — это абстрактный класс доступа к базам данных,
написанный на PHP.
Поясню на примере:
Предположим вы написали скрипт под mysql. И тут заказчик
говорит Вам, что хостинг меняется и там есть только
PostgreSQL. Если вы не использовали класс абстрактного доступа
к базам данных, то вам пришлось бы:
заменить весь код работы с mysql на postgresql
переписать SQL-запросы (так как есть отличия)
Если бы вы использовали абстрактный слой доступа к БД, то
вам скорее всего не пришлось бы менять php-код (только в одном
месте указали бы что используете postgresql) и изменить
SQL-запросы (хотя иногда и это не понадобилось бы).
Я намеренно в этом описании использовал фразу "абстрактный
класс доступа к БД",
поскольку ADODB — не единственный подобный класс.
Наиболее известные конкуренты:
Pear::DB
Pear::MDB
Насколько я знаю, другие классы имеют слабую
функциональность, хотя должен признать, работают быстрее.
Многие пишут такие классы сами, но я не сторонник изобретения
велосипедов.
Противники таких массивных классов, как ADODB или Pear::DB
утверждают, что их использование плохо сказывается на
производительнеости. Да, производительность падает и это
вполне логично. НО:
Скорость не часто является самым важным фактором
(Мало кто из вас пишет сайты с очень большой нагрузкой,
на которых бы это снижение производительности стало
критичным)
Использование таких классов повышает производительность
программиста
При использовании софта, типа phpAccelerator падение
производительности будет не таким заметным (и я не поверю,
что популярные сайты не имеют возможности использовать такой
софт)
Разработчики ADODB написали php-extension, который
ускоряет работу класса (но работать можно и без него)
От себя могу добавить, что многие из написанных мною сайтов
используют ADODB и проблем с производительностью не
имеют.
Можете еще скачать и php-extension, но я его использовать
не пробовал. Чтобы использовать класс, вам необходимо включить
(include) файл ./adodb/adodb.inc.php
3. Простые примеры
Пример 1
<?php // подключаем класс include_once("adodb/adodb.inc.php");
// указываем тип БД $conn = &ADONewConnection('mysql'); // соединяемся с БД $conn->Connect('localhost', 'root', 'password', 'scripts'); // режим отладки —
включен (true) $conn->debug = true; $conn->setFetchMode(ADODB_FETCH_ASSOC); ?></php>
Данный пример демонстрирует подключение к БД. В строке
<?php $conn = &ADONewConnection('mysql'); ?>
Создается объект соединения с базой данных. Именно через
поля и методы данного объекта и будет в дальнейшем вестись
работа с базой данных.
Что касается режима отладки, то по умолчанию он выключен.
При включенном режиме отладки на экран броузера будут
выводиться SQL-запросы и тексты ошибок (если такие были).
Очень упрощает процесс написания и отладки скриптов.
Метод $conn->setFetchMode() — указывает,
каким образом данные о записях будут записаны в массив —
будет ли это ассоциативный массив, или простой нумерованный
или и тот и другой. Ей нужно установить одно из значений (0,
1, 2, 3). Для пояснений приведу код из исходников adodb:
Судя по исходникам ADODB_FETCH_DEFAULT == ADODB_FETCH_BOTH
Теперь сделаем запрос к БД:
<?php // делаем запрос к БД $res = $conn->Execute("SELECT id, title, description FROM
tab"); // если по запросу найдены записи в
таблице if
($res && $res->RecordCount() > 0)
{ //
выводим эти записи в цикле while (!$res->EOF) {
echo "ID = ".$res->fields['id']."\n";
echo "title = ".$res->fields['title']."\n";
echo "description".$res->fields['description']; // переходим к следующей записи $res->MoveNext();
}
} ?>
Вот простейший пример запроса к БД. Метод $conn->Execute() выполняет запрос к базе данных и
возвращает множество записей (recordset). Множество
записей (recordset) — в ADODB является отдельным
объектом, который имеет свои поля и методы для работы с
полученными записями. Некоторые из них использованы в данном
примере.
$res->EOF — равен true если
обработаны все записи множества
$res->fields — хранит ассоциативный
массив значений текущей записи
$res->RecordCount() — возвращает
количество строк, полученных входе выполнения запроса
$res->MoveNext() — переходит к следующей
записи (в массив $res->fields будет занесена
следующая запись множества)
Метод $conn->Execute() — может быть
использован для любых запросов:
$res->AtFirstPage() — возвращает true если текущая страница — первая
$res->AtLastPage() — возвращает true если текущая страница — последняя
$res->LastPageNo() — возвращает номер
последней страницы
4.2 Генерирование
INSERT/UPDATE запросов
Для начала пример:
<?php // пример генерировани INSERT-запроса
// массив, который нужно вставить в таблицу $frm = array("field1"=>"value1", "field2"=>"value2"); // делаем пустой запрос $res = $conn->Execute("SELECT * FROM tab WHERE id =
-1"); // формируем SQL-запрос $sql = $conn->GetInsertSQL($res, $frm); // выполняем запрос $conn->Execute($sql)
// пример генерирования UPDATE-запроса
// получаем данные о строке, которую нужно обновить $res = $conn->Execute("SELECT * FROM tab WHERE id =
17"); $sql = $conn->GetUpdateSQL($res, $frm); // выполняем запрос $conn->Execute($sql) ?>
Так вот идея в том, чтобы все данные, которые нужно
вставить записать в ассоциативный массив. Сделать запрос к БД
чтобы получить имена полей таблицы и сконструировать
SQL-запрос по этим данным.
Уверен, что будет много противников этого метода (мол
лишний SQL-запрос к БД делвть), но мне эти функции кажутся
очень удобными.
4.3 Работа с
транзакциями
Ну это вообще сказка :). Вот пример из мануала:
<?php
$conn->StartTrans(); $conn->Execute("update table1 set val=$val1 where
id=$id"); $conn->Execute("update table2 set val=$val2 where
id=$id"); $conn->CompleteTrans(); ?>
Метод $conn->CompleteTrans(); сам проверит, были
ли ошибки и если так — сделает откат.
ADODB имеет еще и другие функции для работы с
транзакциями, но они устарели и разработчики ADODB рекомендуют
использовать этот вариант.
4.4
Последовательности
Часто при работе с таблицами каждой записи нужно присвоить
уникальный идентификатор, который потом используется в
качестве первичного ключа. Но не все СУБД поддерживают такую
возможность. ADODB эмулирует эту возможность почти для всех
СУБД. На практике это выглядит примерно так:
Метод $conn->GenID() создает последовательность site_users (если она до этого не была создана) и
возвращает значение на единицу больше чем текущее значение
последовательности.
4.5 Кеширование
запросов
ADODB поддерживает серверное кеширование запросов. Суть в
том, что при первом выполнении запроса его результаты
заносятся в кеш-файл. При последующем таком же запросе (если
кеш-файл не устарел) данные будут браться из файла.
Честно говоря, мне не нравится метод, которым они
производят кеширование (по-моему они слишком уж универсальным
сделали его) и предпочитаю делать кеширование своими руками.
Если вас все-таки интересует кеширование, то работает оно
так:
По умолчанию время жизни кеш-файлов — 1 час. Это время
можно изменить 2-мя путями:
<?
$conn->cacheSecs = 24*3600 // 24 часа $rs = $conn->CacheExecute('SELECT * FROM tab');
// или так:
//
время жизни кеша может задаваться первым параметром
// метода CacheExecute $rs = $conn->CacheExecute(24*3500, 'SELECT * FROM tab'); ?>
4.6 Статистика
запросов.
Наверное видели на некоторых сайтах выводится
статистика:
Страница
сгенерирована за 0.0016 секунд. Запросов к базе данных —
12
Как вычисляется время генерирования страницы — к
данной статье не относится, а вот посчитать количество
запросов к БД (а также посчитать количество запросов, взятых
из кеша) ADODB позволяет:
<?php // пример взят из мануала function CountExecs($conn, $sql, $inputarray) {
global $EXECS; $EXECS++;
}
function CountCachedExecs($conn, $secs2cache, $sql, $inputarray) {
global $CACHED; $CACHED++;
}
... // выводим статистику echo "Всего запросов к базе данных:
<b>".$EXECS+$CACHED."</b><br />";
echo "Из них взято из кеша :
<b>".$CACHED."</b>"; ?>
Данные функции вызываются до запроса, поэтому вы можете с
их помощью переписать SQL-запрос.
5. ADODB & PEAR
Я являюсь фанатом как adodb так и репозитария PEAR.
К сожалению основным классом работы с базами данных в PEAR
является PEAR::DB
И многие PEAR-классы используют его. Что же делать
любителям adodb?
Во-первых, если хорошо присмотреться, то классов,
использующих PEAR::DB не так уж и много. У меня почти весь
pear-репозитарий на компьютере и там pear::DB используют
лишь
DB::NestedSet
DB::DataObject
DB::Pager
DB::QueryTool
HTML::Select
XML::sql2xml
Auth
Cache
Log
LiveUser
Mail::Queue
Translation
Во-вторых, многие классы использую "контейнеры", и для этих
классов можно написать контейнер, использующий ADODB (как
писать контейнеры — смотрите на примере контейнеров
pear::DB указанных классов).
В-третьих, ADODB имеет файл adodb-pear.inc.php который
является эмуляцией класса PEAR::DB и остальные классы можно
подогнать под работу с adodb с минимальными телодвижениями
(часто достаточно в тексте класса строку
require_once('DB.php'); заменить на
require_once('adodb-pear.inc.php'); но так бывает не всегда).
Так что ADODB можно успешно применять с pear-классами.
Приведу пример использования adodb c классом
pear::XML::sql2xml. Для тех кто не в курсе — этот класс
трансформирует результат запроса (SELECT) к БД в
XML-строку:
$db = DB::connect("mysql://root@localhost/lot"); $sql2xml = new xml_sql2xml(); $result = $db->getAll("select * from
lot_sessions"); $xmlstring = $sql2xml->getXML($result); ?>
Те кто уже имеют опыт работы с XML_sql2xml наверное чаще
применяют код, который предлагает автор класса
XML_sql2xml:
<?php require_once("XML/sql2xml.php"); $sql2xml = new xml_sql2xml("mysql://root@localhost/lot"); $sql2xml->Add("select * from
lot_sessions"); $xmlstring = $sql2xml->getXML(); ?>
и
<?php
$db = DB::connect("mysql://root@localhost/lot"); $sql2xml = new xml_sql2xml(); $result = $db->query("select * from
lot_sessions"); $xmlstring = $sql2xml->getXML($result); ?>
Оба эти примера не сработают и нужно будет править класс
XML_sql2xml.
6. Заключение
Поскольку статья носит ознакомительный характер, многое
осталось "за кадром". Я не пытался описать все классы, поля и
методы — для этого есть официальная документация. Также я
не описывал функциональные возможности, которые не использовал
на практике:
хранение сессий в БД (в том числе и зашифрованных
сессий)
работа с хранимыми процедурами
работа с БД, находящейся на удаленном сервере
словари (позволяют программно создавать базы данных и
таблицы)