Artykuł poświęcimy klasie DB biblioteki PEAR. Kod wykorzystujący metody getOne(), getAll(), getCol() oraz getRow() klasy DB staje się zwięzły i przejrzysty.
Pobranie i instalacja pakietów PEAR oraz DB
Klasa DB wchodzi w skład biblioteki PEAR. Korzystanie z klasy DB wymaga instalacji dwóch pakietów: pakietu PEAR zawartego w pliku {stala}PEAR-1.4.8.tgz{/stala} oraz pakietu DB (plik {stala}DB-1.7.6.tgz{/stala}). Wszystkie pliki znajdziemy na stronie domowej projektu PEAR pod adresem http://pear.php.net.
Instalacja pakietów PEAR i DB sprowadza się do dwóch czynności: wypakowania spakowanych archiwów, modyfikacji ścieżek dostępu.
Po wypakowaniu plików {stala}PEAR-1.4.1.tgz{/stala} oraz {stala}DB-1.7.6.tgz{/stala} do folderu {stala}c:\\php\\PEAR{/stala} w systemie powinny pojawić się pliki {stala}C:\\php\\PEAR\\PEAR.php{/stala} oraz {stala}c:\\php\\PEAR\\DB.php{/stala}.
Ostatnim krokiem jest modyfikacja ścieżek dostępu. W pliku {stala}php.ini{/stala} modyfikujemy wpis include_path, dołączając na końcu folder, do którego rozpakowaliśmy dwa pakiety biblioteki PEAR:
include_path = \".;c:\php\smarty\libs;c:\php\pear\"
Przykładowa baza danych
Przykłady omówione w artykule wykorzystują bazę danych o nazwie bibliografia. Baza ta zawiera łącznie trzy tabele: {stala}tosoba{/stala}, {stala}tksiazka{/stala} oraz{stala} tautortlumacz{/stala}. Tabela {stala}tosoba{/stala} zawiera informacje na temat autorów i tłumaczy książek. Rekordy tabeli tksiazki odpowiadają pojedynczym książkom.
Tabela {stala}tautortlumacz{/stala} realizuje relację wiele do wielu, jaka łączy tabele {stala}tosoba{/stala} oraz {stala}tksiazka{/stala}.
W tak przygotowanej bazie danych możemy umieszczać informacje o książkach, autorach oraz tłumaczach. Ponieważ tabele {stala}tosoba{/stala} i {stala}tksiazka{/stala} są połączone relacją wiele do wielu, zatem każda książka może mieć dowolnie długą listę autorów oraz tłumaczy.
Przykładowa witryna
Dane zawarte w bazie danych bibliografia udostępniamy w postaci witryny WWW. Witryna składa się z trzech rodzajów stron:
- strona główna, prezentująca wszystkie książki zawarte w bazie danych,
- strona z książkami wybranego autora,
- strona ze szczegółowymi informacjami na temat wybranej książki.
Na każdej ze stron imiona i nazwiska autorów są hiperłączami do stron prezentujących ich książki. Natomiast tytuł książki jest zawsze hiperłączem do strony prezentującej wszystkie informacje na temat konkretnej pozycji. Ponadto nagłówek strony – napis \”Bibliografia\” – jest hiperłączem do strony startowej.
DSN – nazwa źródła danych
Do nawiązania połączenia z bazą danych klasa DB wykorzystuje tzw. nazwę źródła danych (ang. Data Source Name, DSN). DSN jest napisem przypominającym nieco adresy URL. W przypadku stosowania serwera MySQL na komputerze lokalnym DSN przyjmie postać:
mysql://root:alamakota@localhost/bibliografia
W powyższym identyfikatorze, znaczenie poszczególnych fragmentów jest następujące:
mysql - nazwa oprogramowania serwera bazy danych
root - nazwa konta
alamakota - hasło użytkownika root
localhost - adres serwera
bibliografia - nazwa bazy danych
Identyfikator DSN możemy przygotować wykorzystując zmienne:
$user = \'bibliotekarz\';
$pass = \'\';
$host = \'localhost\';
$db = \'bibliografia\';
$dsn = \"mysql://$user:$pass@$host/$db\";
Łączenie i rozłączanie z bazą danych
W celu nawiązania połączenia z bazą danych (listing 1)
require_once \'DB.php\';
$user = \'bibliotekarz\';
$pass = \'\';
$host = \'localhost\';
$db = \'bibliografia\';
$dsn = \"mysql://$user:$pass@$host/$db\";
$dba = DB::connect($dsn);
if (DB::isError($dba)) {
echo \'Bład połaczenia z baza danych!\';
echo $dba->getMessage();
exit();
}
/*
* zapytania SQL
*
*/
$dba->disconnect();
należy utworzyć obiekt $dba wykorzystując statyczną metodę {stala}connect(){/stala}:
$dba = DB::connect($dsn);
Poprawność operacji {stala}connect(){/stala} sprawdzamy funkcją {stala}isError(){/stala}. Funkcja ta jako parametr przyjmuje wynik zwracany przez metody klasy DB (m.in. {stala}connect(){/stala}, {stala}query(){/stala} czy {stala}getRow(){/stala}):
if (DB::isError($dba)) {
echo \'Błąd połączenia z bazą danych!\';
echo $dba->getMessage();
exit();
}
Wydawanie zapytań
Zapytania SQL możemy wykonywać na kilka sposobów. Najwygodniejszym rozwiązaniem jest użycie metod {stala}query(){/stala}, {stala}getAll(){/stala}, {stala}getCol(){/stala}, {stala}getRow(){/stala} oraz {stala}getOne(){/stala}.
Metoda query()
Metoda {stala}query(){/stala} wysyła do serwera zapytanie SQL. Poprawność wykonania zapytania testujemy funkcją {stala}isError(){/stala}. Na przykład zmianę kodowania polskich znaków w zapytaniach i odpowiedziach serwera MySQL zrealizujemy zapytaniem SET NAMES latin2:
$wynik = $dba->query(\'SET NAMES latin2\');
if (DB::isError($wynik)) {
echo \'Błąd zmiany kodowania polskich znaków!\';
echo $wynik->getMessage();
exit();
}
Jeśli po wykonaniu zapytania funkcja {stala}isError(){/stala} (wywołana z parametrem zwróconym przez metodę query()) zwróci wartość true, oznacza to, że zapytanie zakończyło się błędem.
Komunikat wyjaśniający błąd zwraca metoda {stala}getMessage(){/stala}. Zwróćmy uwagę, że metoda ta jest wywoływana dla tej samej zmiennej, którą przekazujemy do metody {stala}isError(){/stala}.
Czasami będzie to więc obiekt $dba (taka sytuacja jest przedstawiona na listingu 1), a czasami – wynik zwracany przez metodę obiektu $dba (np. zmienna {stala}$wynik{/stala} będąca wynikiem wywołania metody{stala}query(){/stala} na listingu 2).
$q = \"
INSERT INTO
tosoba(imie, imie2, nazwisko)
VALUES
(\'Zuzanna\', \'Anna\', \'Kowalska\')
\";
$wynik = $dba->query($q);
if (DB::isError($wynik)) {
echo \'Bład wykonania zapytania SQL!\';
echo $wynik->getMessage();
exit();
}
Metody {stala}query(){/stala} używamy między innymi do dodawania (listing 2) oraz usuwania (listing 3) rekordów z bazy danych.
$q = \"
DELETE FROM
tosoba
WHERE
imie = \'Zuzanna\' AND
imie2 = \'Anna\' AND
nazwisko = \'Kowalska\'
\";
$wynik = $dba->query($q);
if (DB::isError($wynik)) {
echo \'Bład wykonania zapytania SQL!\';
echo $wynik->getMessage();
exit();
}
Metoda getAll()
Do pobrania wyników zapytania w postaci dwuwymiarowej tabeli służy metoda {stala}getAll(){/stala} – listing 4:
$q = \"
SELECT
imie, nazwisko
FROM
tosoba
ORDER BY
nazwisko, imie
\";
$osoby = $dba->getAll($q);
if (DB::isError($osoby)) {
echo \'Bład wykonania zapytania SQL!\';
echo $osoby->getMessage();
exit();
}
foreach ($osoby as $osoba) {
echo \"
{$osoba[0]}
{$osoba[1]}
\";
}
Po wywołaniu metody {stala}getAll(){/stala} zmienna {stala}$osoby{/stala} będzie dwuwymiarową tablicą zawierającą imiona i nazwiska kolejnych osób.
Metoda getCol()
Jeśli wyniki zapytania zawierają jedną kolumnę danych, wtedy możemy użyć metody {stala}getCol(){/stala} – listing 5.
$q = \"
SELECT
tytul
FROM
tksiazka
ORDER BY
tytul
\";
$ksiazki = $dba->getCol($q);
if (DB::isError($ksiazki)) {
echo \'Bład wykonania zapytania SQL!\';
echo $ksiazki->getMessage();
exit();
}
foreach ($ksiazki as $ksiazka) {
echo \"
{$ksiazka}
\";
}
Metoda getRow()
W przypadku gdy zwracane wyniki zawierają jeden wiersz, wówczas stosujemy metodę {stala}getRow(){/stala} – listing 6.
$q = \"
SELECT
tytul, wydawnictwo, cena
FROM
tksiazka
WHERE
tksiazka_id = \'5\'
\";
$ksiazka = $dba->getRow($q);
if (DB::isError($ksiazka)) {
echo \'Bład wykonania zapytania SQL!\';
echo $ksiazka->getMessage();
exit();
}
echo \"Tytuł: {$ksiazka[0]}\";
echo \"Wydawnictwo: {$ksiazka[1]}\";
echo \"Cena: {$ksiazka[2]}\";
Metoda getOne()
Zapytania zwracające pojedynczą liczbę, wykonujemy metodą {stala}getOne(){/stala} – listing 7.
$q = \"
SELECT
COUNT(tksiazka_id)
FROM
tksiazka
\";
$liczba = $dba->getOne($q);
if (DB::isError($liczba)) {
echo \'Bład wykonania zapytania SQL!\';
echo $liczba->getMessage();
exit();
}
echo \"W bazie danych znajduje się $liczba ksiażek.\";
Szablony zapytań
Parametry zapytań umieszczamy w zapytaniach stosując szablony. Dzięki temu klasa DB automatycznie wykona wszelkie wymagane konwersje (np. {stala}addslashes(){/stala} czy {stala}mysql_escape_string(){/stala}). Taki kod jest po pierwsze przenośny pomiędzy różnymi serwerami baz danych, a – co ważniejsze – jest odporny na ataki typu \”zastrzyk SQL\” (ang. SQL Injection). Szablon zapytania przygotowujemy w zmiennej $q, wstawiając w miejsca wypełniane zmiennymi znaki zapytania:
$q = \"
INSERT INTO
tosoba (imie, imie2, nazwisko)
VALUES (?, ?, ?)
\";
Następnie przygotowujemy tablicę zawierającą trzy zmienne, jakie powinny znaleźć się w zapytaniu:
$t = array(\'John\', \'Thomas\', \"O\'Connor\");
Zapytanie wydajemy metodą {stala}query(){/stala}, przekazując szablon zapytania $q oraz zmienne do wypełnienia szablonu $t:
$wynik = $dba->query($q, $t);
Znaki zapytania w szablonie (ang. placeholders) zostaną zastąpione przez kolejne elementy tablicy $t, przy czym wszelkie niedozwolone znaki, na przykład apostrof w nazwisku O\’Connor, zostaną automatycznie poprzedzone ukośnikami.
$q = \"
SELECT
tosoba_id
FROM
tosoba
WHERE
nazwisko < \'K\'
\";
$wynik = $dba->query($q);
if (DB::isError($wynik)) {
echo \'Bład wykonania zapytania SQL!\';
echo $wynik->getMessage();
exit();
}
$liczba_wierszy = $wynik->numRows();
echo \"Liczba zwróconych rekordów: $liczba_wierszy.\";
Listing 9 prezentuje wstawianie rekordu przy użyciu szablonu zapytania. Szablony zapytań możemy stosować również w połączeniu z innymi metodami klasy DB:
$wynik = $dba->getOne($q, $t);
$wynik = $dba->getRow($q, $t);
$wynik = $dba->getCol($q, 0, $t);
$wynik = $dba->getAll($q, $t);
Stosując szablony, należy pamiętać, by w metodzie {stala}getCol(){/stala} podawać numer kolumny.
$q = \"
INSERT INTO
tosoba (imie, imie2, nazwisko)
VALUES (?, ?, ?)
\";
$t = array(\'John\', \'Thomas\', \"O\'Connor\");
$wynik = $dba->query($q, $t);
if (DB::isError($wynik)) {
echo \'Bład połaczenia z baza danych!\';
echo $wynik->getMessage();
exit();
};