Technologie ADOdb kluczem do każdej bazy Jak pisać uniwersalne skrypty PHP 08 2004


CMYK
NA CD NEWSY Z OKŁADKI FIRMA MAGAZYN PROGRAMY WARSZTAT
technologie
ADOdb
kluczem do każdej bazy danych
Tworzenie skryptów niezależnych {
switch($db) {
od bazy danych należy
case  mysql :
$connection = mysql_connect($host, $user, $pass);
do najtrudniejszych zadań
mysql_select_db($database, $db);
programisty. Aby stworzone
break;
case  pg :
programy mogły współpracować
$connection = pg_connect( host=$host port=5432
z każdą bazą danych, potrzeba
dbname=$database user=$user password=$pass );
break;
spójnego interfejsu.
case  sqlite :
Dostarczy go biblioteka ADOdb,
$connection = sqlite_open( $database.sqlite );
break;
której przyjrzymy się bliżej.
}
return $connection;
Paweł Grzesiak
}
?>
ykupując miejsce na serwerze mamy dostęp do jednej, maksymal- Funkcja connect() tworzy interfejs, warstwę abstrakcyjną służącą do połą-
nie dwóch baz danych. Bardzo często jesteSmy skazani na My- czenia z bazą danych. Lecz by mogła działać, potrzebuje wprowadzenia na-
WSQL. I tak powstają skrypty, które pracują wyłącznie na tej bazie. stępujących informacji: typ bazy danych (MySQL, PostgreSQL, czy SQLi-
Problem pojawia się, gdy MySQL przestaje spełniać oczekiwania. Trudno te), nazwa bazy danych, adres serwera, nazwa użytkownika, hasło. Gdy te
przecież przewidzieć jak nasza strona się rozroSnie i czego będziemy po- dane zostaną przekazane do funkcji, nastąpi próba połączenia z bazą danych:
trzebowali w przyszłoSci. Gdy zdecydujemy się na zmianę bazy danych, $db = connect( mysql ,  baza ,  localhost ,
staniemy przed koniecznoScią zmiany skryptów. Zwykle jednak okazuje  uzytkownik ,  haslo );
się to nierealne  jest tyle zmian do dokonania, że lepiej byłoby stworzyć Takim sposobem stworzyliSmy najprostszą z możliwych abstrakcję słu-
oprogramowanie całkowicie od nowa. Takich sytuacji można uniknąć, żącą do nawiązania połączenia z bazą danych. W powyższym przykładzie
wprowadzając poSrednika pomiędzy naszym skryptem a bazą danych. próbujemy połączyć się z bazą MySQL. Funkcja connect() na podstawie
Przyjrzymy się prostemu przykładowi. Połączymy się z trzema bazami zmiennej $db wybiera sekcję kodu, którą ma uruchomić. Jeżeli wszystko się
danych, by zobaczyć, jak wygląda nawiązywanie połączenia w przypadku powiedzie, funkcja w zmiennej $db zwróci identyfikator połączenia. Czy
(kolejno) MySQL, PostgreSQL i SQLite: spełniliSmy założony cel? Czy skrypt jest na etapie połączenia przenoSny?
// MySQL Tak, ponieważ by połączyć się z inną,  dowolną bazą danych, wystarczy
mysql_connect( localhost ,  uzytkownik ,  haslo ); jedynie zmodyfikować parametry przekazywane funkcji connect(). Idąc da-
mysql_select_db( baza ); lej z naszym systemem abstrakcyjnym, należałoby stworzyć obsługę błę-
dów i dalsze funkcje (do wykonywania zapytań, zwracania wyników itd.).
// PostgreSQL Są to już jednak znacznie trudniejsze zadania. Takim sposobem powstałby
pg_connect ( host=localhost port=5432 dbname=baza kompletny system abstrakcyjny do przełączania się pomiędzy obsługiwany-
user=uzytkownik password=baza ); mi bazami danych. Jednak można sądzić, że produkt końcowy byłby bardzo
niedoskonały i wymagałby jeszcze wielu poprawek. Tak trafiamy na
// SQLite ADOdb, czyli coS, co już jest gotowe i z czego możemy korzystać od zaraz.
sqlite_open( baza.sqlite );
Znaczne różnice są widoczne już na pierwszy rzut oka. Począwszy O ADOdb
od nazw funkcji, po przekazywane parametry to samo zadanie wygląda ADOdb (Active Data Objects Data Base) to oprogramowanie, które niwe-
skrajnie różnie. Jak rozwiązać ten problem? Jak napisać skrypt, który luje setki różnic występujących pomiędzy obsługiwanymi przez tę aplika-
prawidłowo połączy się z wybraną bazą? Należy stworzyć warstwę abs- cję bazami danych. A obsługuje niemało, bo kilkadziesiąt rozwiązań bazo-
trakcyjną służącą do połączenia z poszczególnymi bazami danych: danowych, a wSród nich: MySQL, PostgreSQL, Interbase, Informix, Orac-
function connect($db, $database, $host =   , funkcji, za pomocą których wykonuje się wszystkie operacje na bazie da-
$user =   , $pass =   ) nych. W efekcie wszystkie skrypty tworzone w oparciu o ADOdb stają się
Przykłady i programy opisane
w tym artykule znajdują się na dołączonej
84 INTERNET.sierpień.2004
płycie CD w folderze Warsztat_ADOdb
Jak pisać uniwersalne skrypty PHP?
CMYK
WARSZTAT PROGRAMY MAGAZYN FIRMA Z OKŁADKI NEWSY NA CD
technologie
bardziej przenoSne  niezależne od bazy danych. Są także i inne zalety, jak ADOdb w różnych formatach (CHM, HTML). Wszystkie pliki dokumen-
możliwoSć eksportowania wyników do formatu CSV, czy rozbudowana tacji są tradycyjnie w języku angielskim.
diagnostyka ułatwiająca usuwanie błędów i monitorowanie zapytań wyko-
nywanych na bazie danych. Połączenie z bazą danych
Obsługa i korzystanie z ADOdb nie są wcale trudniejsze od pracy ze By rozpocząć pracę z bazą danych, należy się najpierw z nią połączyć.
standardowymi rozszerzeniami PHP. Analogii i podobieństw ADOdb moż- Jakby to wyglądało w bazie MySQL?
na także szukać w standardzie ADO Microsoftu. W ADOdb znajdziemy wiele ułatwień, których brakuje w standardowych API do obsługi baz da- $db = mysql_connect( localhost ,  uzytkownik ,
nych dostępnych w PHP.  haslo );
WydajnoSć komunikacji z bazami danych ma znaczny wpływ na mysql_select_db( baza , $db);
szybkoSć działania skryptów. W ADOdb szybkoSć wykonywania pole- ?>
ceń jest bardzo duża. Na podstawie testów wydajnoSci Podajemy podstawowe dane, wybieramy bazę danych, łączymy się
(http://phplens.com/lens/adodb/) można stwierdzić, że ADOdb przewyższa wiele z MySQL. Teraz dokładnie to samo, stosując już ADOdb:
podobnych rozwiązań dostępnych na rynku. Warto dodać, że ADOdb jest lepszą, szybszą i bogatszą w opcje alternatywą dla PEAR DB include( /adodb/adodb.inc.php );
(http://pear.php.net/package/DB), konkurencyjnej biblioteki wpieranej przez or- $db = &NewADOConnection( mysql );
ganizację PHP w ramach projektu PEAR. ADOdb jednak ustępuje wy- $db->Connect( localhost ,  uzytkownik ,  haslo ,
dajnoScią bibliotekom wbudowanym wprost w język PHP. To logiczne,  baza );
bo jest tylko skryptem PHP, który korzysta z dostępnych w PHP biblio- ?>
tek, by stworzyć wokół nich warstwę abstrakcyjną. Nie może więc prze-
Tabela 1: wybrane bazy danych obsługiwane przez ADOdb
wyższać rozwiązań, z których sam korzysta.
Skrót ADOdb Baza Danych Wymagany sterownik System operacyjny
Wreszcie, największym atutem ADOdb jest wbudowany system buforo-
access Microsoft Access/Jet ODBC Windows
wania zapytań. Zapisuje on do osobnych plików na dysku twardym wyniki
ado ADO, bez wskazania ADO lub OLEDB Windows
pochodzące z zapytań kierowanych do bazy danych. Gdy ponownie zosta-
na konkretną bazę
db2 DB2 interfejs DB2 CLI/ODBC Unix/Windows
nie wykonane to samo zapytanie na bazie danych, ADOdb pobierze wynik
vfp Microsoft Visual FoxPro ODBC Windows
zapytania bezpoSrednio z pliku. Nietrudno dojSć do wniosku, że takie roz-
ibase Interbase 6 lub wcześniejszy klient Interbase Unix/Windows
wiązanie znacznie zwiększa wydajnoSć budowanych na ADOdb aplikacji. firebird Firebird klient Interbase Unix/Windows
ldap sterownik LDAP rozszerzenie LDAP Unix/Windows
A przy tym tworzenie zapytań buforowanych jest tak proste jak zwykłych.
mssql Microsoft SQL Server 7 i starszy klient Mssql Unix/Windows
mysql MySQL bez obsługi transakcji klient MySQL Unix/Windows
mysqlt MySQL z obsługą transakcji. klient MySQL
Instalacja
lub maxsql
Aktualną wersję ADOdb można pobrać z oficjalnej strony biblioteki. Instala-
oci8 Oracle 8/9 klient Oracle Unix/Windows
cja wymaga od nas posiadania dystrybucji PHP w wersji 4.0.4 lub starszej. Na
odbc Standardowy ODBC bez wskazania ODBC Unix/Windows
na konkretną bazę
dołączonej płycie CD zamieSciliSmy aktualną wersję (4.2.2) biblioteki
odbc_mssql MSSQL (używa ODBC by połączyć) ODBC Unix/Windows
ADOdb. Choć trudno tu mówić o instalacji, ponieważ ADOdb to zbiór pli-
odbc_oracle Oracle (używa ODBC by połączyć) ODBC Unix/Windows
ków PHP, należy zastosować się do kilku uwag. Po rozpakowaniu archiwum oracle Oracle 7 (interfejs oci8 lepszy klient Oracle ?
 większa wydajność)
katalog adodb należy wgrać na serwer w miejsce niedostępne (ze względów
postgres PostgreSQL (obecnie identyczny klient PostgreSQL Unix/Windows
bezpieczeństwa katalog z adodb powinien znalexć się w niewidzialnej z ze-
ze sterownikiem postgres7)
wnątrz strukturze serwera) poprzez wpisanie adresu URL. Dla większoSci ser- postgres64 PostgreSQL 6.4 i wcześniejsze, klient PostgreSQL Unix/Windows
nieobsługujące LIMIT
werów za katalog bezpieczny uważa się katalog równorzędny z public_html.
postgres7 PostgreSQL z obsługą LIMIT klient PostgreSQL Unix/Windows
Obok katalogu public_html powinien znalexć się więc katalog adodb.
i zachowaną funkcjonalnością
wersji 7
Ponadto należy stworzyć w tym samym miejscu nowy katalog, do które-
sapdb SAP DB klient SAP ODBC ?
go będą trafiały zapytania buforowane. Może on mieć co prawda dowolną
sqlanywhere Sybase SQL Anywhere klient SQL Anywhere ODBC Unix/Windows
nazwę, lecz my nazwiemy ten katalog: adodbcache. Nowo utworzony kata- sqlite SQLite SQLite (nie dot. PHP5) Unix/Windows
sybase Sybase Sybase client Unix/Windows
log powinien posiadać prawa dostępu również i do zapisu (najlepiej chmod
777). Tak przygotowana instalacja pozwala w pełni korzystać z ADOdb. W pierwszej linii stosując Scieżkę bezwzględną dołączamy bibliotekę
Jeżeli zależy nam na małych rozmiarach instalacji, do poprawnego urucho- ADOdb, która znajduje się w katalogu adodb, patrząc od głównego katalogu
mienia ADOdb w wersji minimalnej potrzebne są następujące pliki: konta. Następnie tworzymy instancję $db klasy NewADOConnection, jako pa-
adodb.inc.php rametr podając typ bazy, skrót odpowiadający sterownikowi do konkretnej ba-
adodb-lib.inc.php zy danych (patrz tabela 1). Kolejno, korzystając z metody Connect, wprowa-
adodb-time.inc.php dzamy wszystkie dane (host, użytkownika, hasło oraz podajemy nazwę bazy).
adodb-php4.inc.php W efekcie otrzymujemy zwrotny identyfikator połączenia ($db). Gdy będzie-
adodb-iterator.inc.php my chcieli zmienić aktualnie obsługiwaną bazę danych na całej stronie, zmia-
Z katalogu drivers (sterowniki) należy też wybrać systemy bazodano- nie podlegają tylko 2 ostatnie linijki powyższego kodu. Wszystkie pozostałe
we, z których mamy zamiar korzystać. Znajdują się tu sterowniki do elementy i funkcje są uniwersalne dla każdej obsługiwanej bazy danych. Gdy-
wszystkich baz danych obsługiwanych przez ADOdb. Gdy zdecydujemy bySmy zatem chcieli przejSć na bazę danych SQLite, powinniSmy zrobić to tak:
się tylko na MySQL, powinniSmy usunąć wszystkie pliki poza adodb-my- sql.inc.php (do dyspozycji mamy jeszcze parę sterowników pobocznych include( /adodb/adodb.inc.php  );
do obsługi MySQL  o tym w dokumentacji). Przy zmianie bazy danych, $db = &NewADOConnection( sqlite );
np. na SQLite, do tego katalogu powinniSmy także wrzucić odpowiedni $db->Connect( /bazy/baza.sqlite );
tej bazie sterownik, czyli adodb-sqlite.inc.php. ?>
W dystrybucji ADOdb w katalogu docs znajdziemy pełną dokumenta- Tu tkwi największa zaleta ADOdb. Wystarczy modyfikacja dwóch
cję opisującą poszczególne funkcje i sposób ich użycia. Na stronie interne- linii kodu, by zmienić bazę danych, na której często pracuje cała strona
towej projektu oraz na dołączonej płycie CD znajduje się dokumentacja internetowa!
INTERNET.sierpień.2004 85
CMYK
NA CD NEWSY Z OKŁADKI FIRMA MAGAZYN PROGRAMY WARSZTAT
technologie
Asocjacyjna czy numeryczna
Instalacja ADOdb jako rozszerzenia PHP
W powyższym przykładzie (wykonanym na bazie MySQL) tablica
wynikowa zawierała elementy tablicy asocjacyjnej (gdzie indeksami
Istnieje możliwość zainstalowania ADOdb również jako modułu rozszerza-
były nazwy pól tabeli) i numerycznej (gdzie indeksami tablicy były
jącego PHP. To rozwiązanie jest dużo wydajniejsze od wersji ADOdb pracują-
cej pod kontrolą PHP. Kod modułu napisany jest (zresztą jak całe PHP) w języ- kolejne liczby, odzwierciedlające kolejne pola tablicy począwszy od
ku C++. Korzystanie z ADOdb jako modułu PHP jest nieco wygodniejsze (nie
zera). W ADOdb wyboru tablicy wynikowej dokonujemy w następują-
trzeba np. każdorazowo dołączać pliku biblioteki). Pojawia się jednak problem
cy sposób:
z przenośnością. O ile pliki ADOdb w formie skryptów PHP przenieść łatwo, to
echo 
 ;
może się okazać, że na innym serwerze nie ma możliwości zainstalowania tego
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
modułu rozszerzającego. Moduł jest również w fazie eksperymentalnej. Można
$rs = $db->GetRow( SELECT * FROM premiery WHERE id=1 );
go pobrać z oficjalnej strony ADOdb. Zamieściliśmy go także na dołączonej
print_r($rs);
płycie. Aktualna wersja ADOdb 3.3.2ext znajduje się w pliku o nazwie adodb-
echo 
 ;
-ext-332.zip. Po rozpakowaniu archiwum, w katalogu php-win-4.3 znajdziemy
żądaną bibliotekę dll. By zainstalować rozszerzenie w Windows, bibliotekę
php_adodb.dll należy przenieść do katalogu extensions, który mieści się
w podkatalogu instalacji PHP. Następnie należy otworzyć plik php.ini, który
kryje w sobie całą lokalną konfigurację PHP. Tam znajduje się sekcja nazwana
 Dynamic Extensions . Na końcu tej listy rozszerzeń należy dodać linijkę:
extension=php_adodb.dll
Wystarczy już tylko uruchomić ponownie serwer, aby ADOdb był standar-
dowo dostępny z poziomu PHP. Informacje na temat instalacji w systemach
uniksowych są dostępne w pliku readme.txt. n
Tablica wynikowa GetRow() jako tablica asocjacyjna
Tabela 2: tabela  Premiery , na której będziemy operować Wyróżniamy trzy wartoSci zmiennej $ADODB_FETCH_MODE:
id tytul_pl tytul data_premiery
1 Dirty Dancing 2 Dirty Dancing: 2004-06-04
ADODB_FETCH_BOTH (zarówno asocjacyjna,
Havana Nights
jak i numeryczna; niektóre bazy nie obsługują tego trybu),
2 Zgromadzenie The Gathering 2004-06-04
ADODB_FETCH_ASSOC (tablica asocjacyjna),
3 Świt żywych trupów Dawn of the Dead 2004-06-11
4 Efekt motyla The Butterfly Effect 2004-06-11
ADODB_FETCH_NUM (tablica numeryczna).
5 The Punisher The Punisher 2004-06-18
6 Ladykillers The Ladykillers 2004-06-18
Istnieje także elegantsza konstrukcja obiektowa:
Przyjrzyjmy się danym w tabeli 2. Jest to tabela o nazwie  premiery z da- $db->SetFetchMode(ADODB_FETCH_NUM);
nymi na temat kilku filmów. Zawiera szeSć rekordów i cztery kolumny. Ma-
my identyfikator liczbowy wiersza (zwiększający się o jeden wraz z kolejnym Buforowanie zapytań
wierszem), polski tytuł filmu (ciąg znaków, VARCHAR), tytuł oryginalny Podczas instalacji ADOdb utworzyliSmy folder adodbcache, który po-
(również VARCHAR) oraz datę premiery (pole typu DATE). Będziemy ko- służy nam teraz do przechowywania danych z zapytań. Gdy wykona-
rzystać z tej tabeli, wykonując na niej wszystkie przykłady. Ze względu na my zapytanie buforowane, wynik tej operacji zostanie zapisany w po-
oszczędnoSć miejsca w wielu przykładach zostaną pominięte trzy pierwsze staci pliku do katalogu adodbcache. Gdy powtórnie wykonamy to sa-
linie skryptu. Dołączamy w nich bibliotekę ADOdb, tworzymy instancję klasy mo zapytanie, zapytanie zamiast trafić powtórnie do bazy danych, zo-
oraz łączymy się z bazą danych (patrz: połączenie z bazą danych). stanie odnalezione w katalogu z plikami buforu. ADOdb pobierze
wyniki operacji wprost z pliku, pomijając całkowicie bazę danych.
Pobieranie jednego wiersza Dzięki temu nasze aplikacje będą pracowały ze zwielokrotnioną pręd-
Za wykonanie zapytania i pobranie do tablicy danych z jednego wiersza koScią. Systemu cachingu używa się tam, gdzie kieruje się do bazy
odpowiada w ADOdb metoda GetRow(). Jej działanie jest analogiczne bardzo dużo identycznych zapytań. Buforowanie ma sens, gdzie dane
do funkcji mysql_fetch_row() i zbliżone do pg_fetch_row(). Poniższy pobierane z buforu nie ulegają zbyt częstej aktualizacji (lub wpływ
przykład pobiera z tabeli  premiery wiersz o id równym 1, zapisując go tych aktualizacji nie jest ważny). Stworzymy więc przykładowe zapy-
do tablicy $rs. Następnie za pomocą funkcji PHP print_r() zostaje gra- tanie buforowane:
ficznie wySwietlony wynik działania skryptu  tablica z danymi. echo 
 ;
echo 
 ; $ADODB_CACHE_DIR =  /adodbcache ;
$rs = $db->GetRow( SELECT * FROM premiery WHERE id=1 ); $rs = $db->CacheGetRow( SELECT * FROM premiery
print_r($rs); WHERE id=1 );
echo 
 ; print_r($rs);
echo 
 ;
W powyższym kodzie pojawiła się nowa zmienna. $ADODB_CA-
CHE_DIR informuje bibliotekę o tym, gdzie znajduje się katalog z pli-
kami buforu. Dodatkowo zmianie uległa nazwa metody GetRow().
Przybył jej przyrostek Cache, ostatecznie mamy więc metodę Cache-
GetRow(). Podobnie będzie z innymi funkcjami. Gdy pierwszy raz zo-
stanie wykonane to zapytanie, w katalogu adodbcache powstanie plik
z wynikami tej operacji. Gdy powtórnie uruchomimy program, dane
powędrują już prosto z pliku. Pliki w buforze przedawniają się jednak
po pewnym czasie  standardowo po 3600 sekundach. Wtedy ADOdb
powtórnie pobiera dane z bazy, by utworzyć nowy, Swieży cache.
Wynik działania metody GetRow() Standardowy czas życia pliku bufora można zmienić, dodając do me-
86 INTERNET.sierpień.2004
CMYK
WARSZTAT PROGRAMY MAGAZYN FIRMA Z OKŁADKI NEWSY NA CD
technologie
tody CacheGetRow() dodatkowy parametr. Jest to wartoSć liczbowa Jeżeli chcemy, by powyższy przykład działał na zasadzie zapytania
wyrażana w sekundach. Jeżeli więc chcemy odSwieżyć cache po buforowanego (czyli był wydajniejszy), należy zmienić nazwę metody
15 minutach, powinniSmy wpisać jako pierwszy parametr wartoSć 900: Execute() na CacheExecute():
$rs = $db->CacheGetRow( 900 ,  SELECT * FROM $rs = $db->CacheExecute( SELECT * FROM premiery );
premiery WHERE id=1 );
Wprowadzanie danych
Pobieranie wielu wierszy By wprowadzić dane do bazy danych, najpierw należy zanegować
Gdy z tabeli chcieliSmy pobrać pojedynczy wiersz, korzystaliSmy kłopotliwe znaki. I tak wszystkie kłopotliwe znaki zostaną poprze-
z funkcji GetRow(). Zajmijmy się teraz sytuacją, gdy z tabeli chcemy dzone odpowiednim dla konkretnej bazy danych symbolem. W My-
pobrać więcej niż jeden wiersz. Kolejny przykład będzie wykorzysty- SQL korzystaliSmy z mysql_escape_string() czy addslashes().
wał metodę Execute(). Jest ona odzwierciedleniem mysql_query() czy W SQLite używaliSmy sqlite_escape_string(), a użycie addslashes()
pg_query()  wykonuje dowolne zapytanie na bazie danych. Gdy ope- groziło błędami. W ADOdb mamy jedną funkcję, która odpowiada
racja się powiedzie, zwraca prawdę, gdy coS się nie powiedzie  fałsz. za przygotowanie ciągu znaków do użycia z metodą Execute(). Me-
Zapytanie wykonane poprawnie należy następnie wySwietlić. Skorzy- tody qstr() należy używać zawsze wtedy, gdy chcemy do bazy
stamy w tym celu z dwóch pętli. Pierwsza zajmie się kolejnymi wier- danych wprowadzić ciąg znaków. Ta funkcja jest o tyle nietypowa,
szami (rekordami), druga kolejnymi komórkami. Skorzystamy także że dodatkowo na końcu i na początku ciągu znaków dodaje znak po-
z metody MoveNext(), która przenosi wewnętrzny wskaxnik wyników jedynczego cudzysłowu  . To zaleta, która nieco skraca zapytanie
o jeden wiersz do przodu. Spójrzmy zatem na przykład: kierowane do bazy. Zaprezentowany poniżej przykład dodaje do ta-
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; beli  premiery nowy wiersz:
$rs = $db->Execute( SELECT * FROM premiery ); // dane do dodania
if (!$rs) $tytul_pl =  Shrek 2 ;
echo $db->ErrorMsg(); $tytul =  Shrek 2 ;
else $data_premiery =  2004-07-02 ;
while (!$rs->EOF) { $query =  INSERT INTO premiery (tytul_pl, tytul,
foreach($rs->fields as $d){ data_premiery) VALUES ( .$db->qstr($tytul_pl). ,
echo $d. ;  ;  .$db->qstr($tytul). ,  .$db->DBDate($data_premiery). ) ;
} $rs = $db->Execute($query);
$rs->MoveNext(); if($rs)
echo 
 ; echo  dodano poprawie! ;
} else
echo 
rekordów:  .$rs->RecordCount(); // zwraca: 6 echo $db->ErrorMsg();
echo 
kolumn:  .$rs->FieldCount(); // zwraca: 4 echo $db->Insert_ID(); // zwróci: 7
W pierwszej linii deklarujemy wynikową tablicę asocjacyjną. echo $db->Affected_Rows(); // zwróci: 1
W następnej linii wykonujemy zwykłe zapytanie na bazie, przypisując Jak widzimy, konstrukcja zapytania niczym specjalnym się nie
wynik do zmiennej $rs. Sprawdzamy, czy zapytanie przebiegło po- wyróżnia. Do zmiennej $query wędruje zapytanie typu INSERT,
prawnie. Jeżeli nie, metoda ErrorMsg() wySwietli informację tekstową które następnie wykonujemy przy użyciu metody Execute(). Jeżeli
na jakie problemy napotkano. Jeżeli zapytanie zostanie wykonane po- operacja się powiedzie, wySwietlany jest komunikat o sukcesie, je-
prawnie, wykonywana jest pętla while. Instrukcje w niej zawarte wy- żeli operacja się nie powiedzie, skrypt informuje o napotkanym błę-
konywane są dotąd, aż wyrażenie !rs->EOF nie zwróci fałszu. Sygnali- dzie. Oprócz sposobu zastosowania metody qstr(), należy również
zator EOF (podobnie jak w operacjach na plikach tekstowych) zwraca zwrócić uwagę na nową metodę, a mianowicie na DBDate(). Auto-
prawdę, gdy pobrane zostaną wszystkie wyniki. Pętla while w naszym rzy ADOdb musieli w jakiS sposób rozwiązać problem wynikający
przypadku wykona się szeSć razy, dla każdego rekordu w tabeli. Pętla z tego, że każda baza danych zapisuje datę w nieco innym formacie.
foreach operuje już na konkretnym wierszu tabeli, na tablicy Tak powstała metoda DBDate(), której jako parametr możemy po-
$rs->fields[]. W każdym wierszu znajdują się cztery komórki, stąd ma- dać datę w dwóch formatach. Może to być (tak jak w przykładzie)
my cztery elementy w tablicy asocjacyjnej $rs->fields[]. WySwietlamy data w standardzie ISO: YYYY-MM-DD lub data w formie unikso-
więc po kolei wszystkie komórki, a ich zawartoSć tkwi w zmiennej $d. wego wskaxnika czasu (timestamp). Data wprowadzona przy użyciu
Wychodząc z pętli foreach widzimy jeszcze metodę MoveNext(). tej funkcji nie powinna rodzić konfliktów i problemów, gdy zmieni-
Pominięcie jej spowoduje, że pętla while nigdy się nie zatrzyma. Pętla my system bazodanowy.
ta odpowiada bowiem za przesunięcie tablicy wyników do następnego
wiersza. Typy danych
Na końcu listingu widoczne są jeszcze dwie metody. Pierwsza Czasami potrzebna jest możliwoSć pobrania informacji o danym polu
z nich, RecordCount() wySwietla liczbę zwróconych wierszy w wyni- w tabeli. Chcemy np. wiedzieć jakiego typu dane tam powinny trafiać
ku. Metoda FieldCount() zwraca liczbę kolumn wynikowych. (jakiego typu danych), czy też chcemy znać maksymalną liczbę zna-
ków jaką można wprowadzić do konkretnego pola. W ADOdb do po-
bierania informacji na temat kolumn w tabeli służy metoda Fetch-
Field(). Przejdxmy do przykładu:
$rs = $db->Execute( SELECT * FROM premiery );
echo 
 ;
print_r($rs->FetchField(1));
echo 
 ;
W pierwszej linii wykonujemy zapytanie na bazie danych. Pobiera-
my informacje na temat wszystkich pól w tabeli ( * ). Następnie ko-
Pobieranie wielu wierszy z tabeli rzystamy z metody FetchField, jako parametr podając numer kolumny
INTERNET.sierpień.2004 87
CMYK
NA CD NEWSY Z OKŁADKI FIRMA MAGAZYN PROGRAMY WARSZTAT
technologie
(począwszy od zera). WySwietlamy informacje na temat 1 kolumny ta- echo rs2csv($rs, false);
beli, czyli nie na temat kolumny ID, a na temat kolumny tytul_pl. Parametr fałszu w przypadku obu funkcji spowoduje, że wynikowe
Funkcja print_r() wySwietli graficznie zawartoSć wynikowego obiektu. dane nie będą zawierały nazw kolumn tabeli. Nie zobaczymy więc pierw-
Są tu informacje na temat nazwy pola, jego maksymalnej długoSci, ty- szego wiersza, gdzie wymienione zostały kolejno: id, tytul_pl, tytul, da-
pu obsługiwanych danych itp. ta_premiery.
Podobnie jak z datami, także z typami danych są problemy co do
zgodnoSci pomiędzy poszczególnymi bazami danych. W jednej ba- Eksportowanie danych do pliku
zie spotkamy się z zapisem typu danych  int , w drugiej  integer . Zapiszemy teraz wynik działania funkcji rs2csv() do pliku. Następnie po-
By w programie mieć pewnoSć o jaki konkretnie typ chodzi, mamy staramy się wydobyć dane z zapisanego uprzednio pliku csv, by wprowa-
do dyspozycji specjalną funkcję. MetaType() na podstawie wprowa- dzić je do bazy danych. W tej sposób najpierw wyeksportujemy dane,
dzonych parametrów: typu danych (np. timestamp, timedate) i mak- a następnie zaimportujemy je do bazy (co doSć często się przydaje).
symalnej długoSci pola (np. 127, 65535) decyduje o jaki typ danych chodzi. Metoda zwraca jedną z dziewięciu wartoSci  liter, które include( adodb/adodb.inc.php );
symbolizują konkretne typy danych (patrz tabela 3). Spójrzmy na include( adodb/toexport.inc.php );
przykład: $db = &NewADOConnection( mysql );
$rs = $db->Execute( SELECT * FROM premiery ); $db->Connect( localhost ,  uzytkownik ,  haslo ,
$inf = $rs->FetchField(1);  baza );
echo $rs->MetaType($inf->type, $inf->max_length); $rs = $db->Execute( SELECT * FROM premiery );
Wykonujemy operacje analogiczne z przedstawionymi w poprzed- $f_loc =  premiery.csv ;
nim przykładzie. Przybywa jedna linia, czyli sposób użycia metody Me- $file = fopen($f_loc,  w );
taType(). W zmiennej $inf znajdują się dane na temat pola tytul_pl. Aby if ($file AND $rs) {
otrzymać informacje na temat typu danych, wprowadzamy jako parame- rs2csvfile($rs, $file, false);
try $inf->type (w tym przykładzie jest to string), $inf->max_length (tu fclose($file);
60 znaków). W efekcie otrzymujemy wynik: C. Przyglądając się tabeli }
stwierdzamy, że pole to musi być typu char lub varchar. Zgadza się. Po- ?>
dobnie można postąpić z pozostałymi kolumnami tabeli. Podobnie jak w poprzednim przykładzie dołączamy potrzebne bibliote-
ki, łączymy się z bazą i wykonujemy zapytanie pobierające do zmiennej
Tabela 3: ustandaryzowane typy danych ADOdb $db zawartoSć tabeli  premiery . Otwieramy do zapisu plik o nazwie za-
wartej w zmiennej $f_loc (prermiery.csv). W przypadku gdy plik nie istnie-
Litera Typ danych Komentarz
C char lub varchar krótkie pola tekstowe; do 255 znaków
je, skrypt utworzy nowy. Jeżeli wszystko przebiegło poprawnie (plik został
X clob lub text duże i bardzo duże pola tekstowe
otworzony do zapisu i zapytanie zostało wykonane poprawnie), funkcja
D date data lub czas
rs2csvfile() załaduje dane do pliku, a następnie plik zostanie zamknięty.
T timestamp uniksowy wskaznik czasu
L boolean lub bitowe wartości 0 (fałsz) lub 1 (prawda)
Funkcja rs2csvfile() to odmiana funkcji rs2csv() przygotowana specjalnie
N decimal, numeric, float, real liczby zmiennoprzecinkowe
do wgrywania danych do plików. Takim sposobem został utworzony plik
I integer liczba naturalna
R autoincrement lub inny licznik pole musi być numeryczne premiery.csv, który można bez problemu otworzyć np. w Excelu.
B blob lub inne obiekty binarne np. obrazy
Eksportowanie danych
Standardowo w ADOdb wbudowane są dwie funkcje służące do ekspor-
towania danych pochodzących z wyników zapytań. Możemy przenieSć
nasze dane do dwóch formatów: CSV (gdzie kolejne komórki oddzielone
są przecinkami) oraz formatu tabularycznego (gdzie kolejne komórki od-
dzielone są znakiem tabulatora). Spójrzmy więc na przykład:
include( adodb/adodb.inc.php );
include( adodb/toexport.inc.php );
$db = &NewADOConnection( mysql );
$db->Connect( localhost ,  uzytkownik ,  haslo ,
 baza );
$rs = $db->Execute( SELECT * FROM premiery );
echo 
 ; Plik premiery.csv można otworzyć m.in. w Excelu
echo rs2tab($rs);
echo 
 ; Importowanie danych z pliku
?> By załadować dane z pliku, musimy go najpierw otworzyć, potem
W powyższym przykładzie należy zwrócić uwagę na to, że ładu- przeanalizować, by wreszcie wrzucić dane do bazy za pomocą zapytań
jemy dodatkową bibliotekę. Biblioteka toexport.inc.php zawiera typu INSERT. Zobaczmy przykład:
dwie funkcje: rs2tab() oraz rs2csv(). Kolejno wykonujemy zapyta- nie pobierające wszystkie dane z tabeli  premiery , a następnie ko- include( adodb/adodb.inc.php );
rzystamy z funkcji rs2tab(), która zwraca nam dane w ustalonym $db = &NewADOConnection( mysql );
formacie. $db->Connect( localhost ,  uzytkownik ,  haslo ,
Teraz przyjrzymy się funkcji rs2csv(). Działa ona dokładnie na ta-  baza );
kiej samej zasadzie, jak ta w powyższym przykładzie. Zarówno dla $query =  INSERT INTO premiery (id, tytul_pl,
rs2csv(), jak i rs2tab() istnieje jeszcze drugi, opcjonalny parametr: tytul, data_premiery) VALUES (?, ?, ?, ?) ;
88 INTERNET.sierpień.2004
CMYK
WARSZTAT PROGRAMY MAGAZYN FIRMA Z OKŁADKI NEWSY NA CD
technologie
$prepared = $db->Prepare($query); tu  value odpowiada drugiej kolumnie zapytania. Drugi parametr
$f_loc =  premiery.csv ; przekazany metodzie GetMenu jest pusty, ponieważ ten parametr usta-
$file = file($f_loc); wia domySlnie wybrany element listy wyboru (gdybySmy chcieli usta-
foreach($file as $line){ wić film  The Punisher jako domySlny, należałoby w tym miejscu
$record = explode( , , $line); wpisać jego nazwę). Trzeci parametr odpowiada za wySwietlenie do-
$rs = $db->Execute($prepared, $record); datkowego pustego pola do wyboru (my wybraliSmy fałsz, co oznacza,
} że na początku listy nie pojawi się puste pole).
rs2html($db->Execute( SELECT * FROM premiery ));
?> Wynik do tabeli HTML
W tym przykładzie spotykamy się z nową metodą. Prepare() nie wy- W ADOdb napotkamy na wiele ułatwień programistycznych. Jednym
konuje zapytania na bazie, lecz informuje bazę danych, że będziemy wy- z takich ułatwień jest funkcja rs2html(). Na podstawie wyników za-
woływać wielokrotnie to samo zapytanie (lecz zmieniały się będą dane pytania automatycznie wygeneruje tabelę HTML. Jednak by skorzy-
oznaczone znakiem zapytania). Takie rozwiązanie pozwala przyspieszyć stać z tej funkcji, musimy dołączyć do wykonywanego skryptu do-
nieco dodawanie rekordów, lecz tylko w przypadku, gdy obsługuje nas datkową bibliotekę: tohtml.inc.php. Szybkie tworzenie tabel ułatwia
baza danych Interbase lub Oracle. W przypadku baz danych nie obsługu- pisanie programów oraz służy do usuwania błędów, a nie do genero-
jących zapytań typu  prepare (np. MySQL) nie odczujemy żadnej różni- wania tabel na strony internetowe. Rzućmy okiem na kompletny
cy w wydajnoSci. Przy użyciu funkcji file() pobieramy do tablicy nume- przykład:
rycznej zawartoSć pliku  premiery.csv . Uzyskaną w ten sposób tablicę wrzucamy w pętle foreach. Spójrzmy co znajduje się w zmiennej $line: include( adodb/adodb.inc.php );
1,Dirty Dancing 2,Dirty Dancing: Havana Nights,2004-06-04 include( adodb/tohtml.inc.php );
Zmienna kryje pierwszą linię, którą znajdziemy w pliku  premie- $db = &NewADOConnection( mysql );
ry.csv . Należy ją teraz podzielić, by kolejnymi elementami tablicy były $db->Connect( localhost ,  uzytkownik ,  haslo ,
poszczególne komórki, które będziemy mogli wrzucić do tablicy. Zrobi-  baza );
my to korzystając z funkcji explode(), która rozdziela ciąg znaków we- $rs = $db->Execute( SELECT * FROM premiery );
dług okreSlonego wzorca i tworzy tablicę z podzielonych skrawków. Na- rs2html($rs);
stępnie przy użyciu metody Execute() wykonujemy zapytanie do bazy. ?>
W tym miejscu pojawia się nowy, drugi parametr. Jest to tablica $record,
która zawiera wynik działania funkcji explode(). ADOdb z tablicy $re-
cord pobierze kolejne jej elementy i zastąpi nimi pytajniki widoczne przy
metodzie Prepared(). Utworzy się tym samym kompletne zapytanie, a da-
ne trafią do bazy. W przykładzie operowaliSmy co prawda na tabeli  pre-
miery , lecz przed wykonaniem przykładu została ona oczyszczona z re-
kordów. W przeciwnym wypadku żadne dane nie trafiłyby do bazy. Dla-
czego? Ponieważ zduplikowalibySmy pola ID, które już istnieją (a takie
zapytanie baza zwyczajnie odrzuci).
rs2html()  wynik zapytania prosto do tabeli HTML
Tworzenie list wyboru
Kolejnym ułatwieniem na które natkniemy się korzystając z ADODb jest
WICEJ O ADODB W SIECI
możliwoSć automatycznego tworzenia HTML-owych list wyboru. Listy
http://php.weblogs.com/ADODB  oficjalna strona projektu ADOdb
typu SELECT tworzy się prosto z wyniku zapytania, co ilustruje poniższy
http://phplens.com/adodb/adodb_tutorial_pl.html  wprowadzenie
przykład (pominięto połączenie z bazą):
do ADOdb w języku polskim
$rs = $db->Execute( SELECT tytul_pl, id FROM
http://php.weblogs.com/portable_sql  jak tworzyć uniwersalne zapytania SQL
premiery ); http://php.weblogs.com/adodb#downloads  aktualna wersja ADOdb
do pobrania
echo  pokaż datę premiery filmu:  ;
http://phplens.com/lens/adodb  testy wydajności ADOdb w stosunku
echo 
 ;
do innych rozwiązań
echo $rs->GetMenu( premiery ,   , false);
echo 
 ;
Podsumowanie
Biblioteka ADOdb jest obecnie najpopularniejszym i najbardziej za-
awansowanym rozwiązaniem oferującym możliwoSć tworzenia skryp-
tów PHP niezależnych od używanego systemu bazodanowego. Umie-
jętnie zaciera różnice występujące pomiędzy dostępnymi na rynku tech-
nologiami bazodanowymi. Obsługuje pokaxną liczbę baz danych, co
daje programiScie duże pole manewru. Niewątpliwą zaletą ADOdb jest
ciągłe udoskonalanie oraz wiele nieoficjalnych rozszerzeń dostępnych
w Internecie. Rozległa i dobra dokumentacja sprawia, że korzystanie
Szybkie tworzenie list wyboru SELECT
z ADOdb jest bardzo wygodne.
W powyższym przykładzie pojawia się jedna nowa metoda. GetMe- ADOdb oferuje ciekawe funkcje w zakresie dynamicznego limitowa-
nu() wykonujemy na zbiorze wyników. By lista wyboru mogła zostać pra- nia i segmentowania wyników. Rozwiązanie to kierowane jest do pro-
widłowo utworzona, musimy dostarczyć dwie wartoSci: gramistów piszących kod wielokrotnego użytku. Tu na mySl przychodzi
zastosowanie ADOdb w Srednich i dużych serwisach internetowych,
Tytuły filmów potrzebne do stworzenia listy są danymi pochodzą- aplikacjach typu CMS czy CRM, gdzie od aplikacji webowej wymaga
cymi z pierwszej kolumny zapytania. Analogicznie zawartoSć elemen- się wieloplatformowoSci i niewielkich wymagań technicznych. n
INTERNET.sierpień.2004 89


Wyszukiwarka

Podobne podstrony:
Przewodnik Klucze do umysłu, czyli jak skutecznie uczyć się języka obcego
Co zrobić, gdy zapomnimy hasło do systemu Windows jak je odzyskać lub zastąpić innym
Jak pisać
Piskulak Kluczem do baśni może wytrych
Jak pisac prace dyplomowa
klucze do Norton Internet Security 2009
Jak pisac prace dyplomowa
jak pisac chwytliwego bloga
Jak pisać protokół z rady
jak pisac i tworzyc prezentacje
E book Poznaj Sekret Jak Pisac Ebooki

więcej podobnych podstron