Vkontakte
+7 (499) 705-13-20
skype: kuzma.feskov

ADODB - русская документация ч.2 - учебник

Автор: Кузьма Феськов, 23 сентября 2014

Оригинал на http://phplens.com/lens/adodb/docs-adodb.htm
Перевод Феськов Кузьма

v4.62 2 Apr 2005 (c) 2000-2005 John Lim (jlim#natsoft.com)

v4.62 14 Июль 2005 (c) 2005 Feskov Kuzma (kuzma#russofile.ru)

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

Учебник

Пример 1: SELECT

Задача: Соединиться с Access Northwind DSN, показать первые 2 колонки каждого ряда.

В этом примере мы создадим объект ADOCOnnection доступа к базе данных. Соединение Pconnet – постоянное. Каждый раз, когда мы хотим сделать запрос к базе данных – вызываем функцию ADOConnection.Execute(). Она возвращает объект ACORecordSet, который, фактически, является курсором, указывающим на текущую строку в массиве fields[]. Мы используем MovieNext() для передвижения по рядам.

Обратите внимание: Полезная функция, которая не используется в данном примере, SelectLimit(), позволяет ограничить количество запрашиваемых рядов.

include('adodb.inc.php'); # подключаем основную библиотеку ADOdb
$conn = &ADONewConnection('access'); # создаем соединение
$conn->PConnect('northwind');   # соединяемся с MS-Access, northwind DSN
$recordSet = &$conn->Execute('select * from products');
if (!$recordSet) 
        print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
        print $recordSet->fields[0].' '.$recordSet->fields[1].' ';
        $recordSet->MoveNext();
}

$recordSet->Close(); # необязательно
$conn->Close(); # необязательно

$recordSet возвращает записи текущего ряда из массива $recordSet->fields с числовыми индексами по номеру колонки (начиная с 0). мы используем функцию MoveNext() для перехода к следующему ряду. EOF устанавливается в TRUE, когда мы достигаем конца. Если происходит ошибка во время запроса, Execute() вернет FALSE вместо запрашиваемых данных.

Массив $recordSet->fields генерируется PHP расширением для работы с базой данных. Некоторые расширения дают только числовой индекс и не дают индекса по названию колонки. Чтобы вызвать индексацию по названию колонки, что является ассоциированным массивом, используйте функцию SetFetchMode. Каждый результат будет сохранен в соответствии с ее установками при создании результата функциями Execute или SelectLimit.

$db->SetFetchMode(ADODB_FETCH_NUM);
$rs1 = $db->Execute('select * from table');
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$rs2 = $db->Execute('select * from table');
print_r($rs1->fields); # shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); # shows array(['col1']=>'v0',['col2'] =>'v1')

Для получения общего количества возвращенных данных, используйте $recordSet->RecordCount(). Помните, что эта функция может вернуть -1, в случае, если невозможно определить количество возвращенных рядов.

Пример 2: Расширенный SELECT с объектами полей

Делаем выборку из таблицы, показываем первые две колонки. Если вторая колонка – дата или тайм штамп, то переформатируем дату в американский формат.

include('adodb.inc.php'); # загружаем библиотеку ADOdb
$conn = &ADONewConnection('access'); # создаем соединение
$conn->PConnect('northwind'); # соединяемся с базой MS-Access, northwind dsn
$recordSet = &$conn->Execute('select CustomerID,OrderDate from Orders');
if (!$recordSet) 
    print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
    $fld = $recordSet->FetchField(1);
    $type = $recordSet->MetaType($fld->type);

    if ( $type == 'D' || $type == 'T') 
        print $recordSet->fields[0].' '.
        $recordSet->UserDate($recordSet->fields[1],'m/d/Y').' ';
    else 
        print $recordSet->fields[0].' '.$recordSet->fields[1].' ';

        $recordSet->MoveNext();
}
$recordSet->Close(); # не обязательно
$conn->Close(); # не обязательно

В этом примере мы проверяем тип второй колонки функцией FetchField(). Эта функция возвращает объект как минимум с тремя полями:

  • name: имя колонки;
  • type: родной тип поля;
  • max_lenght: максимальная длина поля. Некоторые базы, например MySql, неправильно возвращают максимальную длину поля. В этих случаях max_leght будет выставлено в -1.

Далее, мы используем функцию MetaType(), чтобы перевести родной тип поля в родовой тип. В настоящее время определены следующие родовые типы:

  • C: текстовое поле, которое нужно показывать как тег ;
  • X: TeXt, большое текстовое поле, которое необходимо показывать как тег <textarea>;
  • B: Blobs, или бинарные объекты большого объема. Чаще всего – картинки;
  • D: Date, дата;
  • T: Timestamp, тайм штамп;
  • L: логическое поле (булевое (true/false) или бит);
  • I: Integer, целое число;
  • N: Numeric, включает автоприращение (autoincrement), число, число с точкой, реальное и целое число;
  • R: Serial, Включает serial, целые числа с автоприращением. Это работает в отдельных базах данных.

Если metatype имеет тип дата или тайм штамп, то мы печатаем его с использованием заданного пользователем формата в функцией UserDate(), которая конвертирует дату формата PHP SQL в формат, нужный пользователю. Другой вариант использования MetaType() - это приведение (проверка) формата данных перед помещением их в базу данных.

Пример 3: INSERT (вставка)

Вставляем строку в таблицу заказов, которая содержит даты и строки, требующие обработки перед вставкой в базу (слэширование). Например, здесь требует обработки слово John's.

include('adodb.inc.php'); # загружаем бибилиотеку ADOdb
$conn = &ADONewConnection('access'); # создаем соединение
$conn->PConnect('northwind'); # соединяемся с MS-Access, northwind dsn
$shipto = $conn->qstr("John's Old Shoppe");

$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";
$sql .= "values ('ANATR',2,".$conn->DBDate(time()).",$shipto)";

if ($conn->Execute($sql) === false) {
    print 'error inserting: '.$conn->ErrorMsg().'<BR>';
}

В данном примере вы видите расширенные возможности даты, а также возможности по слэшированию строк в ADODB. Unix тайм штамп (который является большим целым числом), соответственно, сформатирован в формат Access функцией DBDate(), а также были расставлены правельные эскейп последовательности для записи 'John's Old Shope' в базу.

Незабывайте обрабатывать ошибки функции Execute(). Она возвратит FALSE в случае ошибки. Текстовое сообщение о последней ошибке может быть показано функцией ErrorMsg(). Внимание: php_track_errors должна быть включена, чтобы иметь возможность записать сообщение об ошибке.

Пример 4: Отладка

include('adodb.inc.php'); # загружаем библиотеку ADOdb
$conn = &ADONewConnection('access'); # создаем соединение
$conn->PConnect('northwind'); # соединяемся с MS-Access, northwind dsn
$shipto = $conn->qstr("John's Old Shoppe");
$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";
$sql .= "values ('ANATR',2,".$conn->FormatDate(time()).",$shipto)";
$conn->debug = true;
if ($conn->Execute($sql) === false) print 'error inserting';

В вышеприведенном примере мы включили отладку, установив debug = true. Это покажет вам SQL запрос перед тем, как его выполнить, а также покажет сообщение об ошибке (в случае ее возникновения). При отладке нет необходимости вызывать функцию ErrorMsg(). Для того, чтобы вывести на экран результат запроса смотрите пример использования функции rs2html.

Также прочитайте раздел Ручная обработка ошибок.

Пример 5: MySql и меню

Соединяемся с базой MySql agora, генерируем <select> на основе SQL запроса, где заголовок <option> - это первая колонка, а значение, содержащее строку для обращения к серверу, - вторая.

include('adodb.inc.php'); # загружаем библиотеку ADOdb
$conn = &ADONewConnection('mysql');  # создаем соединение
$conn->PConnect('localhost','userid','','agora');# соединяемся с MySQL, agora db
$sql = 'select CustomerName, CustomerID from customers';
$rs = $conn->Execute($sql);
print $rs->GetMenu('GetCust','Mary Rosli');

Здесь мы определяем меню по имени GetCust, и где опция Mary Rosli является выбранной. Смотрите GetMenu(). Также в нашем арсенале есть функции, которые возвращают результат в виде массива: GetArray(), и в виде ассоциированного массива: GetAssoc().

Пример 6: Подключение сразу к двум базам данных

include('adodb.inc.php'); # lзагружаем библиотеку ADOdb
$conn1 = &ADONewConnection('mysql'); # создаем соединение
$conn2 = &ADONewConnection('oracle'); # создаем соединение

$conn1->PConnect($server, $userid, $password, $database);
$conn2->PConnect(false, $ora_userid, $ora_pwd, $oraname);

$conn1->Execute('insert ...');
$conn2->Execute('update ...');

Пример 7: Генерация UPDATE и INSERT SQL запросов

Начиная с версии ADODB 4.56 поддерживается функция AutoExecute(), которая упрощает процедуры, выполняемые функциями-преобразователями GetInsertSQL() и GetUpdateSQL(). Например INSERT может быть выполнен следующим образом:

$record["firstname"] = "Bob"; 
$record["lastname"] = "Smith"; 
$record["created"] = time(); 
$insertSQL = $conn->AutoExecute($rs, $record, 'INSERT');

а UPDATE – так:

$record["firstname"] = "Caroline"; 
$record["lastname"] = "Smith"; # меняем фамилию Керолайн со Миранда на Смит
$insertSQL = $conn->AutoExecute($rs, $record, 'UPDATE', 'WHERE id = 1');


Остальная часть данного описания устарела
 

ADODB 1.31 и более поздние версии поддерживают 2 новые функции: GetUpdateSQL() и GetInsertSQL(). Это позволит вам исполнять 'SELECT * FROM tablequery WHERE...', делать копию $rs->fields, изменить поля, и, затем, составить SQL запрос для автоматической вставки или обновления записи.

Мы покажем вам, каким образом эти функции могут использоваться для доступа к таблице со следующими полями: ID, FirstName, LastName, Created.

Прежде, чем вы можете воспользоваться данными функциями, вам необходимо инициализировать рекордсет, произведя выборку из таблицы. Идея принадлежит Jonathan Younger jyounger#unilab.com. Начиная с версии ADODB 2.42 вы можете передавать название таблицы вместо рекордсет в функцию GetInsertSQL(), и это позволит сгенерировать SQL запрос для этой таблицы.

#==============================================
# ПРИМЕР GetUpdateSQL() и GetInsertSQL()
#==============================================
include('adodb.inc.php');
include('tohtml.inc.php');

#==========================
# Этот код проверяет вставляемые данные

$sql = "SELECT * FROM ADOXYZ WHERE id = -1"; 
# Запрашиваем из базы пустой результат

$conn = &ADONewConnection("mysql"); # создаем соединение
$conn->debug=1;
$conn->PConnect("localhost", "admin", "", "test"); # соединяемся с MySQL, testdb
$rs = $conn->Execute($sql); # Выполняем запрос и получаем пустой результат

$record = array(); # Инициализируем массив с данными для вставки

# Устанавливаем значения для колонок
# Обратите внимание, названия колонок регистрозависимы
$record["firstname"] = "Bob";
$record["lastNamE"] = "Smith";
$record["creaTed"] = time();

# Передаем пустой рекордсет и новые данные для вставки
# в функцию GetInsertSQL. Функция обрабатывает данные и возвращает
# полностью сформатированный SQL запрос для вставки.
$insertSQL = $conn->GetInsertSQL($rs, $record);

$conn->Execute($insertSQL); # Вставляем запись в базу данных

#==========================
# Этот код проверяет данные для обновления

$sql = "SELECT * FROM ADOXYZ WHERE id = 1"; 
# Запрашиваем обновляемые данные

$rs = $conn->Execute($sql); # Выполняем запрос и получаем данные, подлежащие обновлению

$record = array(); # Инициализируем массив с данными для обновления

# Устанавливаем значения колонок
# Обратите внимание, названия колонок регистрозависимы
$record["firstname"] = "Caroline";
$record["LasTnAme"] = "Smith"; # Меняем фамилию Кэролайн с Миранды на Смит

# Передаем данные, подлежащие обновлению, и новые данные
# в функцию GetUpdateSQL. Функция обрабатывает данные и возвращает
# полностью сформатированный SQL запрос для обновления с корректным параметром WHERE.
# Если данных для изменения нет – функция вернет пустую строку.
$updateSQL = $conn->GetUpdateSQL($rs, $record);

$conn->Execute($updateSQL); # Обновляем запись в базе данных
$conn->Close();

Пример 8: Организация постраничного вывода

Следующий код показывает как организовать простейший постраничный вывод.

include_once('../adodb.inc.php');
include_once('../adodb-pager.inc.php');
session_start();

$db = NewADOConnection('mysql');

$db->Connect('localhost','root','','xphplens');

$sql = "select * from adoxyz ";

$pager = new ADODB_Pager($db,$sql);
$pager->Render($rows_per_page=5);

В результате вы увидите что-то похожее на это:

|<   <<   >>   >|  
ID First Name Last Name Date Created
36  Alan  Turing  Sat 06, Oct 2001 
37  Serena  Williams  Sat 06, Oct 2001 
38  Yat Sun  Sun  Sat 06, Oct 2001 
39  Wai Hun  See  Sat 06, Oct 2001 
40  Steven  Oey  Sat 06, Oct 2001 
Page 8/10

Количество рядов для вывода контролируется функцией Render(). Если вы не укажите никакого значения – по умолчанию будет выведено 10 записей.

Вы можете изменять названия колонок изменяя свой SQL запрос (поддерживается в большинстве баз данных):

$sql = 'select id as "ID", firstname as "First Name", 
        lastname as "Last Name", created as "Date Created" 
        from adoxyz';

Вышеприведенный пример вы можете найти в примере adodb/tests/testpaging.php, включенном в пакет установки. Класс ADODB_Pager может быть адаптирован программистом для вывода вместо линков картинок, а белый фон – более подходящим цветом.

Также вы можете настроить показ html при помощи $pager->htmlSpecialChars = false.

Часть кода, приведенного здесь, выла написана Ivan Oliva и Cornel G.

Пример 9: Экспорт данных в CVS или с разделением табуляцией

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

include_once('/path/to/adodb/toexport.inc.php');
include_once('/path/to/adodb/adodb.inc.php');

$db = &NewADOConnection('mysql');
$db->Connect($server, $userid, $password, $database);

$rs = $db->Execute('select fname as "First Name", surname as "Surname" from table');

print "<pre>";
print rs2csv($rs); # возвращает строку, CSV формат

print '<hr>';

$rs->MoveFirst(); # Замечание: некоторые базы данных не поддерживают MoveFirst
print rs2tab($rs,false); # возвращает строку, разделитель - табуляция
# false == подавляет название полей на первой линии
print '<hr>';
$rs->MoveFirst();
rs2tabout($rs); # выводит непосредственно на stdout (есть также функция rs2csvout)
print "</pre>";

$rs->MoveFirst();
$fp = fopen($path, "w");
if ($fp) {
  rs2csvfile($rs, $fp); # записываем в файл (есть также функция rs2tabfile)
  fclose($fp);
}

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

Все, описанные выше, функции берут в качестве дополнительного параметра $addtitles, который по умолчанию выставлен в TRUE. Если его установить в FALSE – первая линия не будет содержать названия колонок.

Пример 10: Recordset фильтры

Иногда может потребоваться перед использованием сделать преобразование всех рядов в recordset. Для примера мы преобразуем все текстовые данные в верхний регистр:

include_once('adodb/rsfilter.inc.php');
include_once('adodb/adodb.inc.php');

// ucwords() каждый элемент в recordset
function do_ucwords(&$arr,$rs)
{
    foreach($arr as $k => $v) {
        $arr[$k] = ucwords($v);
    }
}

$db = NewADOConnection('mysql');
$db->PConnect('server','user','pwd','db');

$rs = $db->Execute('select ... from table');
$rs = RSFilter($rs,'do_ucwords');

Функция RSFilter принимает 2 параметра: recordset и название функции фильтра. Возвращает обработанный recordset с указателем на первом элементе. Функция фильтра принимает 2 параметра: текущий ряд как массив и объект recordset. Для будущей совместимости вы не должны использовать оригинальный объект recordset.

Пример 11: Умные транзакции

Старый способ сделать транзакцию требовал, чтобы вы использовали:

$conn->BeginTrans();
$ok = $conn->Execute($sql);
if ($ok) $ok = $conn->Execute($sql2);
if (!$ok) $conn->RollbackTrans();
else $conn->CommitTrans();

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

$conn->StartTrans();
$conn->Execute($sql);
$conn->Execute($Sql2);
$conn->CompleteTrans();

CompleteTrans() обнаруживает возникшие SQL ошибки и делает обратную перемотку или Commit (подтверждение). Вы также можете вызвать обратную перемотку, даже если никакой ошибки не произошло используя функцию FailTrans(). Обратите внимание, что обратная перемотка была сделана в CompleteTrans(), то в FailTrans() она сделана не будет.

$conn->StartTrans();
$conn->Execute($sql);
if (!CheckRecords()) $conn->FailTrans();
$conn->Execute($Sql2);
$conn->CompleteTrans();

Вы также можете проверить, была ли в процессе транзакции ошибка. Для этого воспользуйтесь функцией HasFailedTrans(). Она возвратит TRUE, если вызывалась функция FailTrans() или была ошибка при выполнении SQL запроса. Убедитесь, что вы вызываете функцию HasFailedTrans() перед CompleteTrans(), потому что она выдает результат только между StartTrans/CompleteTrans().

И, наконец, StartTrans/CompleteTrans могут быть вложенными и только самый удаленный блок выполнен. Функции BeginTrans/CommitTrans/RollbackTrans, напротив, НЕ МОГУТ быть вложенными.

$conn->StartTrans();
$conn->Execute($sql);
  $conn->StartTrans();    # игнорируется
  if (!CheckRecords()) $conn->FailTrans();
  $conn->CompleteTrans(); # игнорируется
$conn->Execute($Sql2);
$conn->CompleteTrans();

Обратите внимания, точки сохранения (savepoints) на данный момент не поддерживаются.