Wydawnictwo Helion
ul. Koœciuszki 1c
44-100 Gliwice
tel. 032 230 98 63
e-mail: helion@helion.pl
PEAR.
Programowanie w PHP
Przewodnik po najbardziej przydatnych pakietach PEAR
• Poznaj najpopularniejsze pakiety repozytorium PEAR
• Korzystaj z baz danych za pomoc¹ MDB2
• U¿ywaj gotowych komponentów do szybkiego tworzenia aplikacji w PHP
Jednym z g³ównych powodów popularnoœci PHP jest szeroki dostêp do bibliotek
i rozszerzeñ tego jêzyka. Najwa¿niejszym ich Ÿród³em jest PEAR — internetowe
repozytorium komponentów i aplikacji jêzyka PHP. Pakiety dostêpne w PEAR zawieraj¹
gotowe rozszerzenia umo¿liwiaj¹ce wykonanie niemal wszystkich standardowych
operacji w PHP. Rozszerzenia te przechodz¹ przez œcis³y system kontroli jakoœci,
a ich autorzy musz¹ stosowaæ siê do okreœlonych zaleceñ. Dlatego pisanie programów
z wykorzystaniem pakietów jest nie tylko szybsze, ale prowadzi te¿ do powstawania
lepszych i bardziej spójnych aplikacji.
Dziêki ksi¹¿ce „PEAR. Programowanie w PHP” nauczysz siê wykonywaæ codzienne
zadania programistyczne przy u¿yciu klas z popularnych pakietów PEAR. Dowiesz siê,
jak obs³ugiwaæ bazy danych za pomoc¹ pakietu MDB2, a tak¿e jak wyœwietlaæ dane
zapisane w ró¿nych formatach. Poznasz sposoby tworzenia i analizowania dokumentów
XML oraz przekszta³cania obiektów PHP na format XML i z powrotem. Zobaczysz,
jak tworzyæ w³asne us³ugi WWW oraz u¿ywaæ interfejsów udostêpnianych w us³ugach
autorstwa innych producentów.
• Praca z bazami danych
• Wyœwietlanie informacji w ró¿nych formatach
• Tworzenie i przetwarzanie plików XML
• Przygotowywanie i udostêpnianie us³ug WWW
• Korzystanie z gotowych us³ug WWW
• Praca z datami
Zwiêksz swoj¹ produktywnoœæ, korzystaj¹c z gotowych komponentów
Autorzy: Stephan Schmidt, Stoyan Stefanov,
Carsten Lucke, Aaron Wormus
T³umaczenie: S³awomir Dzieniszewski
ISBN: 978-83-246-0897-3
Tytu³ orygina³u:
PHP Programming with PEAR
Format: B5, stron: 304
Spis tre
Ăci
O autorach
7
Przedmowa
11
Rozdzia
ï 1. MDB2
15
Krótka historia MDB2
16
Warstwy abstrakcji
16
Warstwa abstrakcji dla interfejsu bazy danych
16
Warstwa abstrakcji dla kodu SQL
17
Warstwa abstrakcji dla typów danych
17
Uwarunkowania zwi
Èzane z prÚdkoĂciÈ
17
Konstrukcja pakietu MDB2
18
Zaczynamy prac
Ú z MDB2
19
Instalowanie MDB2
19
Èczenie siÚ z bazÈ danych
20
Tworzenie instancji obiektu MDB2
21
Opcje
21
Definiowanie trybu pobierania danych
23
RozïÈczanie siÚ z bazÈ danych
23
Korzystanie z MDB2
24
Przykïad
24
Wykonywanie zapytañ
25
Pobieranie danych
25
Skróty uïatwiajÈce pobieranie danych
26
Skróty metod query*()
26
Skróty metod get*()
27
Typy danych
29
Ujmowanie wartoĂci i identyfikatorów w cudzysïowy
31
Iteratory
32
Wyszukiwanie bïÚdów
33
PEAR. Programowanie w PHP
4
Warstwa abstrakcji kodu SQL w MDB2
34
Sekwencje
34
OkreĂlanie limitów zapytañ
35
ZastÚpowanie zapytañ
36
Obsïuga subselektów
36
Instrukcje preparowane
37
Transakcje
41
Modu
ïy MDB2
42
Moduï Manager
43
Moduï Function
46
Moduï Reverse
47
W
ïasne rozszerzenia pakietu MDB2
49
Wïasny mechanizm rejestracji w dzienniku
49
Wïasne klasy pobierajÈce dane
51
Wïasne klasy wyników
52
Wïasne iteratory
55
Wïasne moduïy
56
Pakiet MDB2_Schema
57
Instalowanie i tworzenie instancji
57
Tworzenie kopii bazy danych
58
Zmienianie bazy danych
61
Podsumowanie
61
Rozdzia
ï 2. WyĂwietlanie danych
63
Tabele HTML
64
Format tabel HTML
64
Tworzenie prostego kalendarza za pomocÈ HTML_Table
65
Pakiet HTML_Table_Matrix rozszerzajÈcy moĝliwoĂci pakietu HTML_Table
69
Arkusze kalkulacyjne Excela
71
Format Excela
71
Nasz pierwszy arkusz kalkulacyjny
72
Sïowo o komórkach
73
Przygotowywanie strony do wyĂwietlenia
74
Dodawanie formatowania
74
Kolory
75
Wypeïnianie barwnym deseniem
77
Formatowanie liczb
77
Formuïy
79
Wiele arkuszy kalkulacyjnych, obramowania, obrazki
80
Inne techniki tworzenia arkuszy kalkulacyjnych
83
Komponent siatki danych DataGrid
84
½ródïa danych DataSource
85
Renderery
85
Prosta siatka danych DataGrid
86
Stronicowanie wyników
87
Korzystanie ze ěródïa danych DataSource
87
Korzystanie z renderera
88
Spis tre
Ğci
5
Estetyczne formatowanie siatki danych
89
Poszerzanie moĝliwoĂci DataGrid
90
Dodawanie kolumn
91
Generowanie plików PDF
92
Kolory
95
Czcionki
96
Komórki
96
Tworzenie nagïówków i stopek
97
Podsumowanie
98
Rozdzia
ï 3. Praca z formatem XML
99
Pakiety PEAR wspomagaj
Èce pracÚ z XML
100
Tworzenie dokumentów XML
101
Tworzenie obiektów przechowujÈcych informacje o nagraniach
102
Tworzenie dokumentów XML za pomocÈ klasy XML_Util
106
Tworzenie dokumentów XML za pomocÈ pakietu XML_FastCreate
110
Tworzenie dokumentów XML za pomocÈ pakietu XML_Serializer
118
Tworzenie aplikacji Mozilli za pomocÈ pakietu XML_XUL
133
Przetwarzanie dokumentów XML
142
Analizowanie danych XML za pomocÈ pakietu XML_Parser
143
Przetwarzanie kodu XML za pomocÈ pakietu XML_Unserializer
155
Analizowanie danych RSS za pomocÈ pakietu XML_RSS
169
Podsumowanie
173
Rozdzia
ï 4. Usïugi WWW
175
Korzystanie z us
ïug WWW
176
Korzystanie z usïug WWW opartych na XML-RPC
177
SiÚganie do interfejsu API Google
182
Korzystanie z usïug WWW opartych na REST
185
Tworzenie wïasnych usïug WWW opartych na REST
199
Oferowanie us
ïug WWW
208
Oferowanie usïug WWW opartych na protokole XML-RPC
208
Oferowanie usïug WWW opartych na protokole SOAP
216
Oferowanie usïug opartych na protokole REST za pomocÈ pakietu XML_Serializer
223
Podsumowanie
232
Rozdzia
ï 5. Praca z datami
235
Praca z pakietem Date
235
Pakiet Date
236
Obsïuga stref czasowych za pomocÈ klasy Date_Timezone
246
Pakiet PEAR::Date — podsumowanie
250
Pakiet Date_Holidays
250
Wyliczanie ĂwiÈt
254
Czy dziĂ mamy ĂwiÚto?
258
Tïumaczenie nazw ĂwiÈt na inne jÚzyki
259
Pakiet Date_Holidays — podsumowanie
264
PEAR. Programowanie w PHP
6
Praca z pakietem Calendar
264
Podstawowe klasy i pojÚcia zwiÈzane z pakietem Calendar
265
Tworzenie obiektów
268
Sprawdzanie poprawnoĂci obiektów kalendarza
272
Modyfikowanie dziaïania standardowych klas
274
Generowanie danych w formie graficznej
275
Podsumowanie
282
Skorowidz
283
1
MDB2
W ci
Ègu ostatnich dziesiÚciu lat sieÊ WWW bardzo siÚ rozrosïa, jak równieĝ dojrzaïa i sprofesjo-
nalizowa
ïa, w zwiÈzku z czym pojawiïo siÚ zapotrzebowanie na coraz bardziej zïoĝone i dy-
namiczne witryny WWW. Dawniej zupe
ïnie wystarczaïo przechowywanie informacji w pliku
tekstowym lub prostej bazie danych, obecnie jednak ka
ĝdy programista piszÈcy profesjonalnÈ
aplikacj
Ú WWW musi posiadaÊ rzetelnÈ wiedzÚ na temat tego, jak komunikowaÊ siÚ z profe-
sjonalnymi relacyjnymi bazami danych.
Pocz
Èwszy od najwczeĂniejszych wersji jÚzyk PHP zawsze sïuĝyï programistom solidnym
wsparciem w kontaktach z bazami danych. Niemniej do czasu wprowadzenia rozszerzenia
PDO (PHP Data Objects, obiekty danych PHP) nie istnia
ï ĝaden standardowy sposób korzy-
stania z najró
ĝniejszych sterowników baz danych dodawanych do jÚzyka PHP. Brak ujednoli-
conego interfejsu API by
ï oczywiĂcie inspiracjÈ dla kilku projektów majÈcych na celu stwo-
rzenie jakiej
Ă warstwy DBAL (Database Abstraction Layer), która oferowaïaby uniwersalny
poziom abstrakcji dla wszystkich baz danych. G
ïównym celem tych wysiïków byï zamiar
u
ïatwienia ĝycia programistom, tak aby mogli oni pisaÊ kod komunikujÈcy siÚ z bazÈ danych,
który b
Údzie niezaleĝny od sytemu bazy danych wykorzystywanego przez aplikacjÚ. DziÚki
temu klienci lub u
ĝytkownicy mogliby uĝywaÊ aplikacji w poïÈczeniu z tym systemem zarzÈ-
dzania bazami danych, który im najbardziej odpowiada.
Trzy najwa
ĝniejsze z rozpoczÚtych w tamtych latach prób stworzenia warstwy abstrakcji dla
baz danych to: AdoDB, PEAR::DB i Metabase. W ostatnich latach kolejnym bardzo mocnym
kandydatem na uniwersaln
È warstwÚ abstrakcji dla baz danych byï pakiet PEAR::MDB. Ni-
niejszy rozdzia
ï poĂwiÚcony bÚdzie kolejnej inkarnacji MDB, a mianowicie MDB2.
PEAR. Programowanie w PHP
16
Krótka historia MDB2
Wszystko zacz
Úïo siÚ, kiedy Lukas Smith, programista PEAR, opublikowaï kilka ïat do istnie-
j
Ècej juĝ warstwy abstrakcji bazy danych, Metabase. W którymĂ momencie miÚdzy Lukasem
a autorem Metabase wywi
Èzaïa siÚ dyskusja na temat, jakby opublikowaÊ Metabase w repo-
zytorium PEAR jako nowy pakiet. Celem nowego pakietu by
ïoby poïÈczenia funkcjonalnoĂci
oferowanych przez Metabase z interfejsem API istniej
Ècego juĝ i bardzo popularnego pakietu
PEAR::DB. Dzi
Úki temu programiĂci otrzymaliby bogatÈ w funkcje i znakomicie spisujÈcÈ siÚ
bibliotek
Ú abstrakcji bazy danych, co byïoby z wielkÈ korzyĂciÈ dla infrastruktury PEAR. W taki
w
ïaĂnie sposób narodziï siÚ przodek pakietu MDB2, czyli pakiet PEAR::MDB.
Po kilku latach pracy nad pakietem PEAR::MDB, dla autorów sta
ïo siÚ oczywiste, ĝe decyzja
utrzymywania interfejsu API pakietu w takiej formie, aby by
ï jak najbardziej zbliĝony do in-
terfejsów API Metabase i PEAR::DB, nieuchronnie stwarza pewne problemy, które utrud-
niaj
È przeksztaïcenie MDB w peïni profesjonalnÈ warstwÚ abstrakcji bazy danych (DBAL).
Poniewa
ĝ pakiet PEAR::MDB osiÈgnÈï juĝ w repozytorium PEAR stabilnÈ formÚ w peïni doj-
rza
ïego pakietu oprogramowania, niemoĝliwe byïo usuniÚcie pewnych wad bez rezygnacji
z kompatybilno
Ăci z tym starszym moduïem, czego wïaĂnie autorzy starali siÚ za wszelkÈ cenÚ
unikn
ÈÊ. RozwiÈzaniem byïo wykorzystanie doĂwiadczeñ zdobytych podczas prac nad Meta-
base i MDB oraz zastosowanie ich w nowym pakiecie, który zawiera
Ê bÚdzie profesjonalnie
zaprojektowany i w pe
ïni nowoczesny interfejs API. Nowy pakiet otrzymaï nazwÚ MDB2.
Warstwy abstrakcji
Zanim przejdziemy do szczegó
ïowego omawiania, w jaki sposób pakiet MDB2 radzi sobie z two-
rzeniem abstrakcji dla bazy danych, powinni
Ămy najpierw zapoznaÊ siÚ przynajmniej pobieĝ-
nie z teori
È tworzenia warstw abstrakcji obudowujÈcych systemy baz danych, by zrozumieÊ
dok
ïadnie, w jaki sposób siÚ to robi. Na tworzenie warstw abstrakcji dla baz danych moĝna
spojrze
Ê z kilku perspektyw. Omówimy je teraz dokïadniej po kolei i opowiemy, jakie majÈ
wymagania.
Warstwa abstrakcji dla interfejsu bazy danych
Najwa
ĝniejszym etapem w tworzeniu abstrakcji systemu bazy danych jest przygotowanie od-
powiedniej abstrakcji dla interfejsu bazy danych. Dzi
Úki temu programista bÚdzie mógï siÚgaÊ do
baz danych zarz
Èdzanych przez róĝne systemy, uĝywajÈc tych samych metod. Oznacza to, ĝe
zarówno tworzenie po
ïÈczenia z bazÈ danych, wysyïanie zapytania, jak i pobieranie danych
zawsze przebiega
Ê bÚdzie identycznie, niezaleĝnie od tego, z jakÈ bazÈ danych bÚdziemy
wspó
ïpracowaÊ.
Rozdzia
á 1. • MDB2
17
Warstwa abstrakcji dla kodu SQL
Wi
ÚkszoĂÊ obecnie uĝywanych systemów baz danych korzysta ze standardowego zestawu
podstawowych instrukcji SQL, dlatego te
ĝ wiÚkszoĂÊ kodu SQL pisanego przez programistów
powinna dzia
ïaÊ zawsze, niezaleĝnie od tego, z jakiej bazy danych bÚdÈ korzystaÊ. Niemniej
wiele z systemów baz danych wprowadza w
ïasne, specyficzne tylko dla danego systemu in-
strukcje SQL i pomocnicze funkcje, dlatego te
ĝ moĝe siÚ zdarzyÊ, ĝe kod SQL napisany spe-
cjalnie dla jednej bazy danych nie b
Údzie dziaïaï w innej. W miarÚ jak system zarzÈdzania ba-
z
È danych (ang. Relational Database Management System — RDBMS) rozwija siÚ, czasami
implementuje funkcje, które nie s
È kompatybilne ze starszymi wersjami tej samej bazy danych.
Dlatego te
ĝ dla programisty pragnÈcego napisaÊ kod, który byïby zgodny ze wszystkimi wer-
sjami bazy danych (lub który móg
ïby wspóïdziaïaÊ z kilkoma róĝnymi systemami baz danych),
jedynym rozwi
Èzaniem jest ograniczenie siÚ tylko do tych instrukcji kodu SQL, o których
wiadomo,
ĝe na pewno bÚdÈ dziaïaÊ na wszystkich platformach baz danych. LepszÈ opcjÈ jest
jednak skorzystanie ze specjalnej warstwy abstrakcji baz danych, która w razie potrzeby emuluje
odpowiednie funkcje, je
Ăli nie bÚdÈ dostÚpne na danej platformie.
Mimo i
ĝ nie jest wykonalne obudowanie kaĝdej moĝliwej funkcji SQL, pakiet MDB2 obsïu-
guje bardzo wiele powszechnie wykorzystywanych funkcji SQL. Funkcje te to mi
Údzy innymi
obs
ïuga zapytañ LIMIT, subselektów (podzapytañ select) i zapytañ preparowanych. Korzy-
stanie z mechanizmu abstrakcji kodu SQL, oferowanego przez MDB2, daje nam gwarancj
Ú,
ĝe bÚdziemy mogli korzystaÊ z tych zaawansowanych funkcji — nawet wtedy, gdy baza da-
nych, z której korzystamy, samoistnie ich nie obs
ïuguje. W dalszej czÚĂci tego rozdziaïu opo-
wiemy o ró
ĝnych funkcjach oferujÈcych abstrakcjÚ dla zaawansowanych narzÚdzi SQL, które
zapewnia pakiet MDB2.
Warstwa abstrakcji dla typów danych
Na koniec wreszcie konieczne jest przygotowanie abstrakcji dla typów danych stosowanych
przez bazy. Wynika to z faktu,
ĝe róĝne systemy baz danych czÚsto obsïugujÈ typy danych w zu-
pe
ïnie inny sposób.
Uwarunkowania zwi
Èzane z prÚdkoĂciÈ
Zapewne czytelnikom cieknie ju
ĝ Ălinka, by skosztowaÊ tych wspaniaïych funkcji wkompo-
nowanych w pakiet MDB2, niemniej najpierw nale
ĝy powiedzieÊ kilka sïów o zagadnieniach
zwi
Èzanych z prÚdkoĂciÈ i wydajnoĂciÈ. Warto wiedzieÊ, ĝe gdy korzystamy z warstwy abs-
trakcji bazy danych, cz
Ústo za bogactwo funkcji oferowanych przez pakiet dokonujÈcy abs-
trakcji musimy zap
ïaciÊ mniejszÈ wydajnoĂciÈ i szybkoĂciÈ dziaïania bazy danych. Nie jest to
PEAR. Programowanie w PHP
18
tylko u
ïomnoĂÊ pakietu MDB2 ani teĝ warstw abstrakcji bazy danych, ale w ogóle wszelkiego
rodzaju warstw abstrakcji i systemów wirtualizacji.
Na szcz
ÚĂcie, inaczej niĝ w przypadku VMWare lub Miscrosoft Virtual PC, które dokonujÈ
abstrakcji ka
ĝdego wykonywanego wywoïania systemowego, pakiet MDB2 oferuje abstrakcjÚ
tylko wtedy, gdy dana funkcja nie jest dost
Úpna w okreĂlonym systemie baz danych. Oznacza
to,
ĝe wydajnoĂÊ zaleĝeÊ bÚdzie od platformy, na której skorzystamy z MDB2. JeĂli szczegól-
nie zale
ĝy nam na szybkoĂci i wydajnoĂci, to naleĝy skorzystaÊ z pamiÚci podrÚcznej dla ko-
dów operacji (ang. opcode cache) lub w
ïÈczyÊ mechanizm przechowywania zapytañ w pamiÚci
podr
Úcznej w systemie baz danych, którego uĝywamy. DziÚki wykorzystaniu wspomnianych
mo
ĝliwoĂci jÚzyka PHP lub systemu baz danych bÚdziemy mogli w znacznym stopniu ograni-
czy
Ê negatywne efekty spowolnienia dziaïania bazy danych, nieodïÈcznie zwiÈzane z uĝyciem
warstwy abstrakcji.
Konstrukcja pakietu MDB2
Interfejs API pakietu MDB2 zosta
ï zaprojektowany w taki sposób, aby gwarantowaÊ maksi-
mum wszechstronno
Ăci i elastycznoĂci. Poszczególnym obsïugiwanym systemom baz danych
i okre
Ălonym zaawansowanym funkcjom przypisano okreĂlone moduïy. Kaĝdy z licznych ste-
rowników
(ang. drivers) dla baz danych jest osobnym i niezale
ĝnie rozwijanym moduïem PE-
AR. Oznacza to,
ĝe kaĝdy pakiet sterownika funkcjonuje niezaleĝnie, a kolejne wersje i wersje
stabilne publikowane s
È we wïasnych, niezaleĝnych od innych sterowników cyklach. DziÚki
temu programi
Ăci odpowiedzialni za przygotowywanie poszczególnych sterowników mogÈ je
wypuszcza
Ê, ilekroÊ zachodzi taka potrzeba, bez koniecznoĂci czekania na publikacjÚ kolejnej
wersji g
ïównego pakietu MDB2. Pakiet MDB2 moĝe zatem zachowywaÊ stabilnoĂÊ, niezaleĝ-
nie od stanu prac nad pakietami obs
ïugujÈcymi poszczególne sterowniki. W efekcie zdarza siÚ
czasem,
ĝe stabilna wersja pakietu oferuje sterowniki dla niektórych systemów baz danych
jedynie w wersji beta. Ponadto w chwili wypuszczenia nowego sterownika dla bazy danych
oznaczany jest on jako wersja alfa i pakiet podlega procedurze sprawdzania zgodnie ze stan-
dardami repozytorium PEAR.
Drugi rodzaj modu
ïów wbudowanych w pakiet MDB2 to moduïy dodajÈce specjalne, rozszerzone
funkcje oferowane przez pakiet MDB2. Zamiast do
ïÈczaÊ te funkcje do gïównego pakietu MDB2
lub dodawa
Ê do niego nowÈ klasÚ implementujÈcÈ te funkcje, programista ma moĝliwoĂÊ
utworzenia nowej klasy w osobnym module i nast
Úpnie zaïadowanie jej do pakietu MDB2 za
pomoc
È metody
loadModule()
. Gdy ju
ĝ nowy moduï zostanie zaïadowany do pakietu MDB2,
do jego metod b
Údzie moĝna siÚgaÊ w taki sam sposób, jakby byïy metodami wbudowanymi
w pakiet MDB2. Pakiet MDB2 stosuje to rozwi
Èzanie, aby jego wewnÚtrzne pakiety dziaïaïy
tak szybko, jak to tylko mo
ĝliwe, a jednoczeĂnie by pozostawiÊ uĝytkownikom swobodÚ doïÈ-
czania do pakietu MDB2 swoich w
ïasnych klas. Szczegóïowe informacje o tym, jak we wïasnym
zakresie rozwija
Ê pakiet MDB2, moĝna znaleěÊ w dalszej czÚĂci tego rozdziaïu.
Rozdzia
á 1. • MDB2
19
Zaczynamy prac
Ú z MDB2
Poni
ĝej omówimy podstawowe kroki, które trzeba wykonaÊ, by zainstalowaÊ pakiet MDB2,
utworzy
Ê obiekt MDB2 oraz skonfigurowaÊ kilka opcji definiujÈcych tryb pobierania danych.
Na koniec powiemy, jak roz
ïÈczaÊ siÚ z bazÈ danych.
Instalowanie MDB2
Podczas instalowania pakietu MDB2 nale
ĝy pamiÚtaÊ, ĝe nie zawiera on ĝadnych sterowni-
ków baz danych, dlatego trzeba je b
Údzie zainstalowaÊ póěniej osobno. Pakiet MDB2 jest
rozprowadzany w wersji stabilnej, niemniej, jak ju
ĝ wspomnieliĂmy, niektóre z wchodzÈcych
w jego sk
ïad moduïów sterowników i rozszerzeñ mogÈ byÊ rozwijane w niezaleĝnych cyklach,
dlatego niektóre z wykorzystywanych przez nas modu
ïów mogÈ byÊ dopiero w wersji beta,
alfa lub nawet jeszcze w fazie programowania. Nale
ĝy o tym pamiÚtaÊ podczas instalowania
pakietów zawieraj
Ècych sterowniki poszczególnych baz danych.
Najpro
Ăciej jest zainstalowaÊ MDB2 korzystajÈc z programu instalacyjnego repozytorium PEAR:
> pear install MDB2
To polecenie zainstaluje klasy tworz
Èce rdzeñ MDB2, natomiast nie zainstaluje ĝadnego z do-
st
Úpnych sterowników baz danych. Aby zainstalowaÊ sterownik wïaĂciwy dla systemu baz da-
nych, którego u
ĝywamy, naleĝy skorzystaÊ z polecenia:
> pear install MDB2_Driver_mysql
To akurat polecenie zainstaluje sterownik dla bazy MySQL. Aby zainstalowa
Ê sterownik dla
bazy SQLite, nale
ĝy wpisaÊ:
> pear install MDB2_Driver_sqlite
Oto pe
ïna lista dostÚpnych aktualnie sterowników:
■
fbsql
— Front Base
■
ibase
— InterBase
■
mssql
— MS SQL Server
■
mysql
— MySQL
■
mysqli
— system MySQL korzystaj
Ècy z rozszerzenia mysqli PHP; wiÚcej
informacji pod adresem: http://php.net/mysqli
■
oci8
— Oracle
■
pgsql
— PostgreSQL
■
querysim
— Querysim
■
sqlite
— SQLite
PEAR. Programowanie w PHP
20
Èczenie siÚ z bazÈ danych
Aby po
ïÈczyÊ siÚ z wybranÈ bazÈ danych juĝ po udanym zainstalowaniu pakietu MDB2 i mo-
du
ïu sterownika, konieczne bÚdzie najpierw okreĂlenie nazwy ěródïa danych, DSN (Data Source
Name). Nazwa DSN mo
ĝe mieÊ postaÊ ïañcucha lub tablicy i definiuje parametry poïÈczenia
z baz
È danych takie jak: nazwa bazy danych, typ systemu RDBMS (systemu zarzÈdzajÈcego rela-
cyjn
È bazÈ danych), nazwa uĝytkownika i hasïo wykorzystywane do ïÈczenia siÚ z bazÈ danych itp.
Nazwa DSN jako tablica
Je
Ăli nazwa ěródïa danych, DSN, jest definiowana w formie tablicy, bÚdzie wyglÈdaÊ mniej
wi
Úcej tak:
$dsn = array ( 'phptype' => 'mysql',
'hostspec' => 'localhost:3306',
'username' => 'user',
'password' => 'pass',
'database' => 'mdb2test'
);
Oto lista ró
ĝnych kluczy parametrów uĝywanych w tablicy nazwy DSN:
■
phptype
— nazwa wykorzystywanego sterownika; innymi s
ïowy: nazwa definiujÈca
system RDBMS
■
hostspec
— (specyfikacja hosta) okre
Ăla nazwÚ hosta, na którym dziaïa baza danych;
mo
ĝe przyjmowaÊ postaÊ
host:port
lub te
ĝ podawaÊ tylko samÈ nazwÚ hosta, a port
b
Údzie wtedy definiowany osobno w kluczu
port
■
database
— nazwa bazy danych, z któr
È siÚ ïÈczymy
■
dbsyntax
— je
Ăli uĝywana skïadnia jest inna niĝ wïaĂciwa dla systemu
phptype
■
protocol
— wykorzystywany protokó
ï komunikacyjny, na przykïad TCP
■
socket
— gniazdo, które nale
ĝy okreĂliÊ, jeĂli ïÈczymy siÚ za poĂrednictwem gniazd
■
mode
— s
ïuĝy do definiowania trybu otwierania pliku bazy danych
Nazwa DSN jako
ïañcuch
Szybszym i bardziej przyjaznym dla cz
ïowieka sposobem (gdy juĝ siÚ do niego przyzwycza-
imy) jest definiowanie nazw DSN za pomoc
È ïañcucha tekstowego wyglÈdajÈcego podobnie
do adresu URL. Zasadniczo, jego sk
ïadnia wyglÈda tak:
phptype://nazwa-uĝytkownika:hasïo@specyfikacja-hosta/baza-danych
gdzie
phptype
to oczywi
Ăcie typ systemu baz danych. Dla systemu MySQL ïañcuch nazwy DSN
mo
ĝe wyglÈdaÊ na przykïad tak:
$dsn = 'mysql://user:pass@localhost:3306/mdb2test';
Rozdzia
á 1. • MDB2
21
Wi
Úcej informacji na temat nazw DSN oraz inne przykïady prawidïowych ïañcuchów DSN
mo
ĝna znaleěÊ w podrÚczniku repozytorium PEAR, dostÚpnym pod adresem: http://pear.php.net/
¦
manual/en/package.database.mdb2.intro-dsn.php
.
Tworzenie instancji obiektu MDB2
Istniej
È trzy metody umoĝliwiajÈce tworzenie (instancjacjÚ) obiektu MDB2:
$mdb2 =& MDB2::connect($dsn);
$mdb2 =& MDB2::factory($dsn);
$mdb2 =& MDB2::singleton($dsn);
Metoda
connect()
tworzy obiekt i
ïÈczy siÚ z bazÈ danych. Metoda
factory()
tworzy obiekt,
natomiast po
ïÈczenie utworzy dopiero, gdy bÚdzie ono potrzebne. Wreszcie metoda
single-
ton()
dzia
ïa podobnie jak metoda
factory()
, ale upewnia si
Ú, ĝe istnieje tylko jeden obiekt
MDB2 o danej nazwie
ěródïa danych, DSN. JeĂli wiÚc taki obiekt juĝ istnieje, metoda zwraca
ten obiekt, a je
Ăli nie, tworzy nowy.
Istnieje te
ĝ sposób „zakïócania” dziaïania metody
singleton()
za pomoc
È metody
setDatabase()
,
która pozwala okre
ĂliÊ, ĝe bieĝÈca baza danych ma byÊ inna niĝ ta okreĂlona w nazwie DSN.
$dsn = 'mysql://root@localhost/mdb2test';
$mdb2_first =& MDB2::singleton($dsn);
$mdb2_first->setDatabase('inna_db');
$mdb2_second =& MDB2::singleton($dsn);
W tym przypadku b
Údziemy mieli dwie róĝne instancje MDB2.
Wszystkie trzy wspomniane metody tworz
È obiekt klasy sterownika bazy danych. JeĂli na
przyk
ïad korzystamy ze sterownika bazy MySQL, zmienna
$mdb
zdefiniowana powy
ĝej bÚdzie
instancj
È klasy
MDB2_Driver_mysql
.
Opcje
Pakiet MDB2 udost
Úpnia kilka opcji, które moĝna definiowaÊ przywoïujÈc metody
connect()
,
factory()
lub
singleton()
lub te
ĝ póěniej korzystajÈc z metody
setOption()
(by zdefiniowa
Ê
jedn
È opcjÚ) lub
setOptions()
(by zdefiniowa
Ê kilka opcji na raz). Na przykïad:
$options = array ( 'persistent' => true,
'ssl' => true,
);
$mdb2 =& $MDB2::factory($dsn, $options);
lub
$mdb2->setOption('portability', MDB2_PORTABILITY_NONE);
PEAR. Programowanie w PHP
22
Pe
ïnÈ listÚ dostÚpnych opcji moĝna znaleěÊ w dokumentacji interfejsu API pakietu MDB2,
dost
Úpnej pod adresem: http://pear.php.net/package/MDB2/docs/. Przyjrzyjmy siÚ teraz dwóm
najwa
ĝniejszym opcjom.
Opcja „persistent”
Jest to opcja logiczna, która okre
Ăla, czy utworzone poïÈczenie powinno byÊ poïÈczeniem trwa-
ïym, czy teĝ nie.
W witrynie
mysql.com
mo
ĝna znaleěÊ bardzo dobry artykuï na temat zalet i wad korzystania z trwaïych
po
ïÈczeñ z bazÈ danych w systemie MySQL. Naleĝy zajrzeÊ pod adres:
http://www.mysql.com/news-and- events/
newsletter/2002-11/a0000000086.html
.
Domy
Ălnie przypisywana jest jej wartoĂÊ
false
(fa
ïsz), okreĂlajÈca, ĝe poïÈczenie nie powinno
by
Ê trwaïe. Podczas tworzenia obiektu moĝna zmieniÊ to domyĂlne ustawienie:
$options = array ( 'persistent' => true
);
$mdb2 =& MDB2::factory($dsn, $options);
Natomiast metoda
setOption()
pozwala definiowa
Ê opcje juĝ po utworzeniu obiektu:
$mdb2->setOption('persistent', true);
Opcja „portability”
Pakiet MDB2 próbuje poradzi
Ê sobie jakoĂ z róĝnicami w sposobie implementowania pew-
nych funkcji baz danych przez ró
ĝne systemy RDBMS. Opcja
portability
pozwala okre
ĂliÊ,
w jakim zakresie warstwa bazy danych ma dba
Ê o przenoĂnoĂÊ naszych skryptów.
Ró
ĝne wartoĂci opcji
portability
definiowane s
È jako staïe zaczynajÈce siÚ od
MDB2_PORTABI-
LITY_*
, a domy
Ălna wartoĂÊ opcji to
MDB2_PORTABILITY_ALL
i oznacza „zrób wszystko, co tylko
mo
ĝliwe, by zagwarantowaÊ przenoĂnoĂÊ skryptów”. PeïnÈ listÚ staïych dla opcji
portability
oraz ich opis mo
ĝna znaleěÊ pod adresem: http://pear.php.net/manual/en/package.database.
¦
mdb2.intro-portability.php
.
Mo
ĝna definiowaÊ kilka wartoĂci opcji
portability
, jak równie
ĝ definiowaÊ wyjÈtki za pomo-
c
È operatorów bitowych — dokïadnie w taki sposób, w jaki definiuje siÚ zasady raportowania
b
ïÚdów w jÚzyku PHP. To na przykïad ustawienie poleca dbaÊ o przenoĂnoĂÊ w peïnym zakre-
sie, z wyj
Ètkiem stosowania maïych liter:
MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_LOWERCASE
Je
Ăli natomiast nie interesujÈ nas wszystkie funkcje przenoĂnoĂci oferowane przez MDB2,
a chcieliby
Ămy tylko usunÈÊ z wyniku spacje i zmieniÊ puste wartoĂci na ïañcuchy
null
, to
nale
ĝy uĝyÊ opcji:
Rozdzia
á 1. • MDB2
23
MDB2_PORTABILITY_RTRIM | MDB2_PORTABILITY_EMPTY_TO_NULL
Prawdopodobnie najlepszym rozwi
Èzaniem bÚdzie jednak pozostawienie domyĂlnego usta-
wienia
MDB2_PORTABILITY_ALL
. W ten sposób, w przypadku jakich
Ă problemów z aplikacjÈ, bÚ-
dziemy wiedzieli,
ĝe kod zwiÈzany z siÚganiem do bazy danych zostaï dodatkowo sprawdzony
pod k
Ètem wspóïpracy z róĝnymi systemami baz danych.
Definiowanie trybu pobierania danych
Kolejnym ustawieniem, które warto zdefiniowa
Ê na poczÈtku, jest tryb pobierania danych
(ang. fetch mode) lub te
ĝ innymi sïowy — sposób, w jaki dane te bÚdÈ nam zwracane. Moĝe-
my otrzymywa
Ê dane w postaci uporzÈdkowanej listy (ustawienie domyĂlne), w formie tablic
asocjacyjnych lub w formie obiektów. Oto przyk
ïady definiowania trybu pobierania danych:
$mdb2->setFetchMode(MDB2_FETCHMODE_ORDERED);
$mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
$mdb2->setFetchMode(MDB2_FETCHMODE_OBJECT);
Oczywi
Ăcie najbardziej przyjaznym dla czïowieka i najczÚĂciej stosowanym trybem pobiera-
nia danych b
Údzie pobieranie ich w tablicach asocjacyjnych, poniewaĝ wyniki umieszczane sÈ
wtedy w tablicy, której klucze odpowiadaj
È nazwom kolumn tabeli w bazie danych. Aby poka-
za
Ê, na czym polega róĝnica, przyjrzyjmy siÚ róĝnym sposobom pobierania danych zawartych
w naszym zbiorze wyników:
echo $result[0];
// uporz
ądkowana lub indeksowana tablica, domyĞlnie w MDB2
echo $result['name'];
// tablica asocjacyjna
echo $result->name;
// obiekt
Jest jeszcze jeden tryb pobierania danych, o nazwie
MDB2_FETCHMODE_FLIPPED
(tryb odwróco-
ny). Jest on cokolwiek nietypowy i jego dzia
ïanie zostaïo w dokumentacji API pakietu MDB2
opisane w nast
ÚpujÈcy sposób:
„W przypadku wyników wielowymiarowych, zazwyczaj pierwszy poziom tablic jest numerem
wiersza, podczas gdy drugi poziom jest indeksowany wed
ïug nazwy bÈdě numeru kolumny.
Tryb
MDB2_FETCHMODE_FLIPPED
odwraca ten porz
Èdek, w efekcie czego pierwszy poziom tablic
b
Údzie nazwÈ kolumny, a drugi poziom — numerem wiersza”.
Roz
ïÈczanie siÚ z bazÈ danych
Aby roz
ïÈczyÊ siÚ z bazÈ danych, naleĝy uĝyÊ nastÚpujÈcego kodu:
$mdb2->disconnect();
Niemniej nawet je
Ăli sami nie zaznaczymy w kodzie, ĝe chcemy rozïÈczyÊ siÚ z bazÈ danych,
pakiet MDB2 zrobi to za nas automatycznie w swoim destruktorze.
PEAR. Programowanie w PHP
24
Korzystanie z MDB2
Gdy ju
ĝ poïÈczymy siÚ z bazÈ danych i okreĂlimy odpowiednie opcje poïÈczenia oraz tryb po-
bierania danych, b
Údzie moĝna przystÈpiÊ do wykonywania zapytañ. Na potrzeby przykïadów
prezentowanych w tym rozdziale za
ïoĝymy, ĝe mamy tabelÚ o nazwie
people
(ludzie), z ko-
lumnami
id
(identyfikator),
name
(imi
Ú),
family
(nazwisko) i
birth_date
(data_urodzenia):
id
name
family
birth_date
1
Eddie
Vedder
1964-12-23
2
Mike
McCready
1996-04-05
3
Stone
Gossard
1966-07-20
Przyk
ïad
Oto prosty przyk
ïad pokazujÈcy, jak korzystaÊ z MDB2. W dalszej czÚĂci opowiemy o wszyst-
kim szczegó
ïowo, teraz jednak rzuÊmy okiem na kod, starajÈc siÚ zrozumieÊ w ogólnym zarysie,
jak on dzia
ïa.
<?php
require_once 'MDB2.php';
// przygotowania
$dsn = 'mysql://root:secret@localhost/mdb2test';
$options = array ('persistent' => true);
$mdb2 =& MDB2::factory($dsn, $options);
$mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
// wykonujemy zapytanie
$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);
// wy
Ğwietlamy imiona
while ($row = $result->fetchRow())
{
echo $row['name'], '<br />';
}
// zwalniamy wykorzystywane zasoby
$result->free();
// wy
áączamy zapytania
$mdb2->setOption('disable_query', true);
// usuwamy trzeci rekord
$id = 3;
$sql = 'DELETE FROM people WHERE id=%d';
Rozdzia
á 1. • MDB2
25
$sql = sprintf($sql, $mdb2->quote($id, 'integer'));
echo '<hr />Zmienione wiersze: ';
echo $mdb2->exec($sql);
// zamykamy po
áączenie
$mdb2->disconnect();
?>
Wykonywanie zapyta
ñ
Aby wykona
Ê zapytanie, moĝna uĝyÊ metod
query()
lub
exec()
. Metoda
query()
zwraca
obiekt wyniku
MDB2_Result
, natomiast metoda
exec()
zwraca liczb
Ú wierszy w tabelach zmie-
nionych przez zapytanie. Dlatego te
ĝ metoda
exec()
b
Údzie bardziej odpowiednia w przy-
padku zapyta
ñ, które modyfikujÈ dane.
Mimo i
ĝ metoda
query()
pozwala wykona
Ê praktycznie kaĝdÈ operacjÚ na bazie danych, MDB2
oferuje równie
ĝ inne metody, które lepiej nadajÈ siÚ do okreĂlonych, czÚsto wykonywanych
operacji.
Pobieranie danych
W przedstawionym wy
ĝej przykïadzie moĝna znaleěÊ nastÚpujÈce wiersze:
$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);
Zmienna
$result
jest obiektem wyniku typu
MDB2_Result
lub te
ĝ, ĂciĂlej mówiÈc, zaleĝnÈ od
konkretnego sterownika bazy danych klas
È, która jest rozszerzeniem typu
MDB2_Result
, na
przyk
ïad
MDB2_Result_mysql
. Do przegl
Èdania zbioru wyników moĝna natomiast uĝyÊ w pÚtli
metody
fetchRow()
, która pobiera pojedyncze wiersze.
while ($row = $result->fetchRow())
{
echo $row['name'], '<br />';
}
Za ka
ĝdym razem gdy przywoïujemy metodÚ
fetchRow()
, sprawdzi ona nast
Úpny rekord i zwróci
odwo
ïanie (ang. reference) do zawartych w nim danych. Oprócz metody
fetchRow()
jest jesz-
cze par
Ú innych metod z grupy
fetch*()
:
■
fetchAll()
zwraca od razu tablic
Ú zawierajÈcÈ wszystkie rekordy.
■
fetchOne()
je
Ăli zostanie przywoïana bez ĝadnych parametrów, zwraca wartoĂÊ
pierwszego pola z bie
ĝÈcego wiersza. Natomiast jeĂli przeĂlemy jej odpowiednie
parametry, b
Údziemy mogli za jej pomocÈ pobraÊ dowolne pole z dowolnego
wiersza. Na przyk
ïad wywoïanie
fetchOne(1,1)
zwróci w naszym przyk
ïadzie imiÚ
Mike
, czyli drug
È kolumnÚ drugiego wiersza.
PEAR. Programowanie w PHP
26
■
fetchCol($column)
zwraca pola w kolumnie o numerze
$column
dla wszystkich
wierszy lub te
ĝ pierwszÈ kolumnÚ, jeĂli parametr
$column
nie zostanie okre
Ălony.
Warto zwróci
Ê uwagÚ, ĝe metody
fetchRow()
i
fetchOne()
przenosz
È wewnÚtrzny wskaěnik do
bie
ĝÈcego rekordu, podczas gdy metody
fetchAll()
i
fetchCol()
przenios
È go na koniec zbio-
ru wyników. Mo
ĝna równieĝ skorzystaÊ z wywoïania
$result->nextResult()
, by z jego pomoc
È
przenie
ĂÊ wskaěnik do nastÚpnego rekordu w zbiorze wyników lub z wywoïania
$result->
seek($rownum)
, by przenie
ĂÊ wskaěnik do wiersza okreĂlonego w parametrze
$rownum
. W razie
w
ÈtpliwoĂci moĝna teĝ skorzystaÊ z wywoïania
$result->rowCount()
, by sprawdzi
Ê, w którym
miejscu zbioru wyników aktualnie znajduje si
Ú nasz wskaěnik.
Mo
ĝna równieĝ ustaliÊ liczbÚ wierszy i liczbÚ kolumn w zbiorze wyników:
$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);
echo $result->numCols();
// wy
Ğwietla 4
echo $result->numRows();
// wy
Ğwietla 3
Skróty u
ïatwiajÈce pobieranie danych
Bardzo cz
Ústo znacznie wygodniej jest pobieraÊ dane w formie tablicy asocjacyjnej (lub zdefi-
niowa
Ê je jako preferowany tryb pobierania danych) i nie kïopotaÊ siÚ szczegóïami technicz-
nymi zwi
Èzanymi z przeglÈdaniem zbioru wyników. Pakiet MDB2 oferuje dwa zestawy metod
umo
ĝliwiajÈcych pobieranie danych „na skróty”: metody z grupy
query*()
i metody z grupy
get*().
Za ich pomoc
È nastÚpujÈce czynnoĂci wykonuje siÚ przy uĝyciu pojedynczego wy-
wo
ïania metody:
1. Wykonywanie zapytania
2. Pobieranie zwracanych danych
3. Zwalnianie zasobów wykorzystywanych przez pobrany wynik
Skróty metod query*()
W tej grupie mamy do dyspozycji metody
queryAll()
,
queryRow()
,
queryOne()
i
queryCol()
,
które odpowiadaj
È analogicznym metodom z grupy
fetch*()
, omówionym wy
ĝej. Oto przy-
k
ïad ilustrujÈcy, czym róĝni siÚ korzystanie z metod z grupy
query*()
od metod
fetch*()
:
// instrukcja SQL
$sql = 'SELECT * FROM people';
// jeden ze sposobów pobierania wszystkich danych
$result = $mdb2->query($sql);
$data = $result->fetchAll();
$result->free();
// nie wymagane
// krótszy sposób
$data = $mdb2->queryAll($sql);
Rozdzia
á 1. • MDB2
27
W obu przypadkach, je
Ăli wyĂwietlimy za pomocÈ metody
print_r()
zawarto
ĂÊ zmiennej
$data
i korzystamy z trybu pobierania u
ĝywajÈcego tablic asocjacyjnych, otrzymamy:
Array ( [0] => Array ( [id] => 1
[name] => Eddie
[family] => Vedder
[birth_date] => 1964-12-23
)
[1] => Array ( [id] => 2
[name] => Mike
[family] => McCready
[birth_date] => 1966-04-05
)
...
)
Skróty metod get*()
Oprócz metod z grupy
query*()
mo
ĝna jeszcze korzystaÊ ze skrótów oferowanych przez metody
get*()
. Metody z grupy
get*()
generalnie zachowuj
È siÚ w taki sam sposób jak metody z grupy
query*()
, niemniej pozwalaj
È równieĝ na stosowanie w zapytaniach parametrów. Rozwaĝmy
nast
ÚpujÈcy przykïad:
$sql = 'SELECT * FROM people WHERE id=?';
$mdb2->loadModule('Extended');
$data = $mdb2->getRow($sql, null, array(1));
W tym przyk
ïadzie znak zapytania pojawiajÈcy siÚ w instrukcji jest zmiennÈ, która zostanie
zast
Èpiona wartoĂciÈ przesïanÈ w trzecim parametrze metody
getRow()
.
Mo
ĝna równieĝ korzystaÊ z parametrów posiadajÈcych wïasne nazwy:
$sql = 'SELECT * FROM people WHERE id=:the_id';
$mdb2->loadModule('Extended');
$data = $mdb2->getRow( $sql,
null,
array('the_id' => 1)
);
Warto zwróci
Ê uwagÚ na to, ĝe metody
get*()
s
È czÚĂciÈ moduïu Extended pakietu MDB2,
co oznacza,
ĝe aby byïy dostÚpne, naleĝy je najpierw zaïadowaÊ uĝywajÈc polecenia
$mdb2->
loadModule('Extended')
.
Dzi
Úki ïadowaniu moduïów mamy moĝliwoĂÊ przeciÈĝania obiektów, czego nie moĝna byïo
robi
Ê przed pojawieniem siÚ PHP5. Dlatego w wersji PHP4 jÚzyka, aby siÚgnÈÊ do metod
modu
ïu Extended, trzeba je byïo przywoïywaÊ w nastÚpujÈcy sposób:
$mdb2->extended->getAll($sql);
PEAR. Programowanie w PHP
28
Natomiast obecnie wystarczy wpisa
Ê:
$mdb2->getAll($sql);
getAsoc()
Kolejn
È uĝytecznÈ metodÈ z grupy
get*()
, która nie ma bezpo
Ăredniego odpowiednika w grupie
fetch*()
ani w grupie
query*()
, jest metoda
getAssoc()
. Zwraca ona wyniki w podobny spo-
sób jak metoda
getAll()
, niemniej kluczami w tablicy wyników b
ÚdÈ wartoĂci z pierwszej
kolumny tabeli. Dodatkowo zbiór wyników zawiera (w naszym przyk
ïadzie) tylko dwie ko-
lumny, poniewa
ĝ jednÈ wykorzystaliĂmy juĝ jako indeks tablicy. Druga kolumna zostanie
zwrócona w formie
ïañcucha (a nie w formie tablicy z jednym elementem). Oto kilka przykïadów
ilustruj
Ècych róĝnice pomiÚdzy metodami
getAll()
i
getAssoc()
:
$sql = 'SELECT id, name FROM people';
$mdb2->loadModule('Extended');
$data = $mdb2->getAll($sql);
Metoda
getAll()
zwróci uporz
ÈdkowanÈ tablicÚ, w której kaĝdy z elementów bÚdzie tablicÈ
asocjacyjn
È zawierajÈcÈ wszystkie pola.
Array ( [0] => Array ( [id] => 1
[name] => Eddie
)
[1] => Array ( [id] => 2
[name] => Mike
)
...
)
Je
Ăli wykonalibyĂmy to samo zapytanie za pomocÈ metody
getAssoc()
, na przyk
ïad wpisujÈc
w kodzie
$data=$mdb2->getAssoc($sql)
, to otrzymaliby
Ămy nastÚpujÈcy wynik:
Array ( [1] => Eddie
[2] => Mike
[3] => Stone
)
Je
Ăli zapytanie zwraca wiÚcej niĝ dwie kolumny, to kaĝdy z wierszy bÚdzie tablicÈ, a nie skala-
rem. Oto kod wykonuj
Ècy takie zapytanie:
$sql = 'SELECT id, name, family FROM people';
$mdb2->loadModule('Extended');
$data = $mdb2->getAssoc($sql);
A oto wynik:
Array ( [1] => Array ( [name] => Eddie
[family] => Vedder
)
...
)
Rozdzia
á 1. • MDB2
29
Typy danych
Aby poradzi
Ê sobie z problemem wynikajÈcym z tego, ĝe róĝne systemy bazy danych obsïu-
guj
È róĝne typy danych dozwolone dla pól tabel, pakiet MDB2 dostarcza wïasnego, uniwer-
salnego zestawu typów danych. Programista mo
ĝe korzystaÊ z typów danych oferowanych
przez MDB2 i pozwoli
Ê, by sam pakiet MDB2 zadbaï o przenoĂnoĂÊ typów danych miÚdzy
ró
ĝnymi systemami RDBMS, po prostu mapujÈc swoje typy na typy odpowiedniego systemu
baz danych.
Oto lista typów danych oferowanych przez MDB2 i ich domy
Ălne wartoĂci:
$valid_types = array ( 'text' => '',
'boolean' => true,
'integer' => 0,
'decimal' => 0.0,
'float' => 0.0,
'timestamp' => '1970-01-01 00:00:00',
'time' => '00:00:00',
'date' => '1970-01-01',
'clob' => '',
'blob' => '',
)
Wi
Úcej informacji na temat typów danych MDB2 moĝna znaleěÊ w pliku datatypes.html,
znajduj
Ècym siÚ w podkatalogu docs w katalogu, w którym zainstalowaliĂmy PEAR. Doku-
ment ten jest równie
ĝ dostÚpny w internecie, w witrynie repozytorium PEAR CVS:
http://cvs.php.net/viewcvs.cgi/pear/MDB2/docs/datatypes.html?view=co
Okre
Ălanie typów danych
We wszystkich metodach s
ïuĝÈcych do pobierania danych, którym siÚ do tej pory przyglÈdali-
Ămy (z grup
query*()
,
fetch*()
i
get*()
), mo
ĝna byïo okreĂlaÊ typ zbioru wyników, który
chcemy otrzyma
Ê, i pakiet MDB2 automatycznie konwertowaï wartoĂci na odpowiedni typ
danych. Na przyk
ïad metodzie
query()
mo
ĝna byïo przesïaÊ jako drugi parametr tablicÚ za-
wieraj
ÈcÈ oczekiwane typy danych dla pól:
$sql = 'SELECT * FROM people';
$types = array();
$result = $mdb2->query($sql, $types);
$row = $result->fetchRow();
var_dump($row);
W tym przypadku tablica typów
$types
by
ïa pusta, wiÚc metoda zachowaïa siÚ w domyĂlny
sposób (nie wykonuj
Èc ĝadnej konwersji typów danych) i wszystkie wyniki zostaïy zwrócone
w formie
ïañcuchów. Przykïad ten zwraca nastÚpujÈce dane:
PEAR. Programowanie w PHP
30
array(2)
{
["id"] => string(1) "1"
["name"]=> string(5) "Eddie"
...
}
Mo
ĝemy jednak zaĝyczyÊ sobie, aby pierwsze pole w kaĝdym zwracanym rekordzie byïo typu
integer
(ca
ïkowitoliczbowego), a drugie typu
text
(tekstowego), definiuj
Èc tablicÚ
$type
w nast
Ú-
puj
Ècy sposób:
$types = array('integer', 'text');
W tym przypadku otrzymamy nast
ÚpujÈcy wynik:
array(2)
{
["id"]=> int(1)
["name"]=> string(5) "Eddie"
...
}
Podczas okre
Ălania typów moĝna równieĝ uĝyÊ tablicy asocjacyjnej, w której kluczami bÚdÈ
poszczególne pola tabeli. W takim przypadku mo
ĝna nawet pominÈÊ niektóre pola, jeĂli nie
chcemy dla nich definiowa
Ê typów. Oto przykïady poprawnych definicji takiej tablicy:
$types = array( 'id' => 'integer',
'name' => 'text'
);
$types = array('name'=>'text');
$types = array('integer');
Okre
Ălanie typów danych podczas pobierania wyników
Je
Ăli nie chcemy okreĂlaÊ typów danych juĝ podczas przywoïywania metody
query()
, mo
ĝemy
to zrobi
Ê póěniej. Zanim rozpoczniemy pobieranie danych, moĝemy okreĂliÊ typy danych
u
ĝywajÈc metody
setResultTypes()
.
//
wykonujemy zapytanie
$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);
//
pobieramy pierwszy wiersz bez konwertowania typów
$row = $result->fetchRow();
var_dump($row['id']);
// wynik b
Ċdzie nastĊpujący: string(1) "1"
//
okre
Ğlamy typy
$types = array('integer');
$result->setResultTypes($types);
Rozdzia
á 1. • MDB2
31
//
wszystkie nast
Ċpne pobrania bĊdą konwertowaü
//
pierwsz
ą kolumnĊ na liczbĊ caákowitą
$row = $result->fetchRow();
var_dump($row['id']);
// wynik b
Ċdzie nastĊpujący: int(2)
Okre
Ălanie typów danych dla metod get*() i query*()
Wszystkie metody z grup
get*()
i
query*()
, które omawiali
Ămy wyĝej w tym rozdziale, po-
zwalaj
È na okreĂlanie w drugim przesyïanym im parametrze, jakie typy danych majÈ zwracaÊ.
Dok
ïadnie tak samo jak w metodzie
query()
.
Mo
ĝemy definiowaÊ parametr przesyïajÈcy typy danych nie tylko jako tablicÚ
$types = array('in-
teger')
, ale równie
ĝ jako ïañcuch
$types = 'integer'
. Jest to wygodne, kiedy pracujemy
z metodami, które maj
È zwracaÊ tylko jednÈ kolumnÚ danych, takimi jak
getOne()
,
queryOne()
,
getCol()
czy
queryCol()
, niemniej nale
ĝy bardzo ostroĝnie korzystaÊ z tej techniki w przy-
padku metod typu
*All()
i
*Row()
, poniewa
ĝ wówczas ïañcuch w parametrze podajÈcym typ
okre
Ăli typ dla wszystkich pól w zbiorze danych.
Ujmowanie warto
Ăci i identyfikatorów w cudzysïowy
Ró
ĝne systemy RDBMS zarzÈdzajÈce relacyjnymi bazami danych stosujÈ róĝne konwencje
ujmowania danych w cudzys
ïowy (na przykïad tam gdzie jedne uĝywajÈ pojedynczych cudzy-
s
ïowów
'
, inne stosuj
È podwójne cudzysïowy
"
). Nie ma te
ĝ ĝadnej powszechnie przyjÚtej
konwencji ujmowania w cudzys
ïowy typów danych. Na przykïad w systemie MySQL moĝe-
my (je
Ăli chcemy) ujmowaÊ wartoĂci typu
integer
(ca
ïkowitoliczbowe) w cudzysïowy, nato-
miast w innych systemach mo
ĝe to byÊ zabronione. Z tego powodu wïaĂnie lepiej pozostawiÊ
obs
ïugÚ cudzysïowów warstwie abstrakcji bazy danych, poniewaĝ pakiet MDB2 „wie”, jakie
konwencje stosuj
È tutaj róĝne systemy baz danych.
Pakiet MDB2 oferuje specjaln
È metodÚ
quote()
, która umo
ĝliwia ujmowanie danych w cu-
dzys
ïowy, i metodÚ
quoteIdentifier()
pozwalaj
ÈcÈ na ujmowanie w cudzysïowy nazw baz
danych, tabel i pól. Wszelkie cudzys
ïowy wstawione przez pakiet MDB2 bÚdÈ odpowiednie
dla wykorzystywanego systemu RDBMS. Oto przyk
ïad:
$sql = 'UPDATE %s SET %s=%s WHERE id=%d';
$sql = sprintf( $sql,
$mdb2->quoteIdentifier('people'),
$mdb2->quoteIdentifier('name'),
$mdb2->quote('Eddie'),
// domniemany typ danych
$mdb2->quote(1, 'integer')
// wyra
Ĩnie okreĞlony typ danych
);
Je
Ăli teraz w bazie MySQL wykonamy polecenie
echo $sql
, otrzymamy:
UPDATE `people` SET `name`='Eddie' WHERE id=1