PHP Co nowego w PHP 5 (cz 3) 11 2004

background image

C

M

Y

K

SQLite

SQLite posiada sporo cech, które odró¿niaj¹ to rozwi¹zanie od typo-
wych baz danych. Niektórzy lubi¹ j¹ okreœlaæ jako plikow¹ bazê da-
nych. Do przechowywania wszystkich danych wykorzystuje ona bo-
wiem pliki. Gdy tworzymy bazê danych w SQLite, tworzymy plik na
dysku serwera, który póŸniej otwieramy i wykonujemy na nim zapyta-
nia. To rozszerzenie PHP5 jest wiêc czymœ w rodzaju miniaturowej ba-
zy danych, która nie potrzebuje otwieraæ osobnych procesów, by mog³a
pracowaæ. Co wiêcej, w PHP5 baza SQLite dostêpna jest domyœlnie,
nie musimy wiêc niczego ju¿ instalowaæ. Instalujemy PHP5, a wraz
z nim dostajemy w pe³ni dzia³aj¹c¹ bazê danych. Za pomoc¹ rozszerze-
nia SQLite mo¿emy utworzyæ w dowolnej chwili now¹ bazê danych.
SQLite utworzy plik na dysku serwera, dok³adnie o takiej nazwie jak¹
sami ustalimy. Nastêpnie mo¿emy wykonaæ na tej bazie zapytania, np.
dodaæ nowe tabele do bazy wraz z danymi. SQLite jest niemal w 100%
zgodny z jêzykiem SQL92. Bez przeszkód wykonamy dowolne zapyta-
nia typu SELECT, UPDATE, INSERT, stworzymy w³asne funkcje
(piszemy je w PHP, a póŸniej wykorzystujemy podczas pracy z SQLi-
te), widoki, zapytania podrzêdne, prze³¹czniki, transakcje.

SQLite to baza opieraj¹ca siê o pliki tekstowe, ma wiêc kilka wad,

które charakteryzuj¹ tego typu rozwi¹zania:

!

nie mo¿na modyfikowaæ dotychczasowych struktur tabeli za
pomoc¹ sk³adni ALTER TABLE, choæ jest to problem mo¿liwy
do obejœcia,

!

brak jest mo¿liwoœci tworzenia obcych kluczy,

!

widoki pracuj¹ tylko w trybie do odczytu,

!

nie dzia³aj¹ polecenia RIGHT OUTER JOIN i FULL OUTER
JOIN,

!

nastêpuje blokowanie dostêpu do pliku bazy danych podczas
zapisu.

Baza SQLite jest przede wszystkim znakomitym substytutem

dla p³askich baz danych i jest w stanie wyprzeæ je w ca³oœci. P³a-
skie bazy danych to wszelkiego rodzaju pliki tekstowe, które maj¹
s³u¿yæ do nieskomplikowanego przechowywania danych. Kolejne
rekordy w takich bazach oddziela znak nowej linii, natomiast kolej-
ne rekordy oddziela siê wed³ug upodobania autora rozwi¹zania, np.
tabulatorem.

SQLite ma szanse odnieœæ sukces g³ównie dlatego, ¿e jest rozwi¹-

zaniem dostêpnym domyœlnie wraz z PHP5. Za jego szansami na suk-
ces przemawia wiele faktów:

!

prostota korzystania,

!

brak koniecznoœci instalacji i konfiguracji,

!

wydajnoœæ, szczególnie w transakcjach,

!

tymczasowe bazy tworzone w pamiêci serwera,

!

interfejs u¿ytkownika zbli¿ony do MySQL.

O SQLite Czytelnicy MI mieli ju¿ okazjê siê dowiedzieæ z artyku-

³ów opublikowanych w numerach 4 i 5/2004. W pierwszej czêœci zna-
laz³o siê szczegó³owe omówienie zastosowañ i mo¿liwoœci SQLite.
Druga czêœæ to praktyczna prezentacja mo¿liwoœci SQLite wraz
z przyk³adami realizacji poszczególnych zadañ. Dlatego te¿ w trzeciej
czêœci kursu wprowadzaj¹cego do PHP5 nakreœlone zostan¹ jedynie
podstawowe zagadnienia dotycz¹ce pracy z SQLite w sposób obiekto-
wy, poniewa¿ praca z SQLite w paradygmacie obiektowym jest do-
stêpna dopiero od PHP5. Artyku³ z maja prezentowa³ jedynie przyk³a-
dy w formie proceduralnej, dostêpne zarówno w PHP4, jak i w PHP5.

Interfejs obiektowy

W PHP5 ma dominowaæ interfejs obiektowy. Do jego obs³ugi zosta³
przystosowany równie¿ i interfejs bazy SQLite:

PHP

INTERNET.listopad.2004

100

NA CD

NEWSY

Z OK£ADKI

FIRMA

MAGAZYN

PROGRAMY

WARSZTAT

!

W ostatniej czêœci wprowadzenia do PHP5
skupimy siê na tematyce obs³ugi baz
danych w PHP5. Korzystanie z baz danych
w jêzykach skryptowych jest obecnie
tak oczywiste, ¿e nie sposób wyobraziæ
sobie strony, która nie wykorzystywa³aby
baz danych. Lecz o ile w PHP4 dominowa³
model LAMP – Linux Apache MySQL PHP,
o tyle w PHP5 mamy do czynienia z trendem
ku zmianom.

Pawe³ Grzesiak

PHP5

CO NOWEGO W

(cz. 3)

Bazy danych

UWAGA!

Poprzednie części tego cyklu

są na płycie CD!

Wszystkie przykłady opisane w artykule

znajdują się na dołączonej płycie CD

w katalogu Warsztat_PHP.

background image

C

M

Y

K

<?
$sqlite = new SQLiteDatabase(”jakasbaza.sqlite”);
$sqlite->query(’CREATE TABLE jakastabela

!

(id INTEGER PRIMARY KEY, a, b);

INSERT INTO jakastabela (a,b) VALUES

!

(”abcd”, ”1.43”);’);

echo ’Ostatnio dodany ID: ’.$sqlite->

!

lastInsertRowid();
$array = $sqlite->arrayQuery(’SELECT * FROM

!

jakastabela WHERE id = 1’, SQLITE_ASSOC);
print_r($array);
?>

Nowy obiekt bazy danych SQLite tworzymy poprzez utworzenie

instancji klasy SQLiteDatabase, podaj¹c przy tym parametr w postaci
nazwy pliku bazy danych. Je¿eli plik ten nie istnieje, baza danych o ta-
kiej nazwie zostanie utworzona na dysku serwera. W przyk³adzie za
pomoc¹ metody query() tworzymy tabelê sk³adaj¹c¹ siê z trzech ko-
lumn. Pierwsza kolumna jest typu INTEGER PRIMARY KEY, co od-
powiada MySQLowemu typowi auto_increment. Pozosta³e kolumny
nie posiadaj¹ typu, poniewa¿ SQLite nie wymaga ich podawania. Dla
SQLite jest ca³kowicie obojêtnie jaki typ danych podamy, bowiem ta
baza ich nie u¿ywa. Posiada w³asne mechanizmy, które przy sortowa-
niu danych wykryj¹ jakiego typu danych jest kolumna i podejd¹ do
kwestii sortowania w sposób doœæ specyficzny (o czym by³a mowa
w artykule „SQLite cz. 2”, MI 5/2004). Poniewa¿ podczas jednego
wywo³ania metody query() mo¿na wykonaæ dowoln¹ iloœæ zapytañ,
oprócz utworzenia tabeli wprowadzamy do niej ponadto jeden przyk³a-
dowy rekord. Nastêpna linia przyk³adu, zawieraj¹ca wywo³anie meto-
dy lasInsertRowId(), zwróci identyfikator liczbowy ostatnio dodanego
wiersza. Kolejno skorzystamy z metody arrayQuery, która jest swoje-
go rodzaju kompilacj¹ metod query() i fetch_array(). Pierwszym para-
metrem przy wywo³ywaniu tej metody jest zapytanie, natomiast dru-
gim sposób odbioru danych (tu: tablica asocjacyjna). Wynikiem dzia-
³ania tej metody jest tablica asocjacyjna, któr¹ wyœwietlamy na ekranie
przy u¿yciu print_r.

Wynik realizacji powy¿szego przyk³adu jest nastêpuj¹cy:

Ostatnio dodany ID: 1
Array
(

[0] => Array

(

[id] => 1
[a] => abcd
[b] => 1.43

)

)

Praca z SQLite jest zbli¿ona do pracy z MySQL. Zmiany w nazew-

nictwie w interfejsie obiektowym spowodowa³y jednak niewielk¹ nie-
zgodnoœæ nazw w porównaniu z poprzednim stanem.

Bazy typu :memory:

Bardzo interesuj¹c¹ w³aœciwoœci¹ bazy danych SQLite jest mo¿liwoœæ
tworzenia baz danych, które zostan¹ ulokowane w pamiêci serwera. S¹
one szczególnie przydatne, gdy musimy dokonaæ obróbki jakichœ da-
nych, a nie chcemy do tego celu tworzyæ klasycznej bazy danych zapi-
sanej na dysku twardym serwera. Wówczas bazy typu :memory:
dostarcz¹ potrzebnych narzêdzi, jednoczeœnie nie stwarzaj¹c potrzeby
lokowania bazy na dysku serwera, lecz w jego ulotnej pamiêci. W pro-
sty sposób mo¿na utworzyæ bazê danych typu „:memory:”:

<?
$sqlite = new SQLiteDatabase(”:memory:”);
$sqlite->query(’CREATE TABLE jakastabela

!

(id INTEGER PRIMARY KEY, a, b);

INSERT INTO jakastabela (a,b) VALUES

!

(”abcd”, ”1.43”)’);

echo ’Ostatnio dodany ID: ’.$sqlite->lastInsertRowid();
$array = $sqlite->arrayQuery(’SELECT * FROM

!

jakastabela WHERE id = 1’, SQLITE_ASSOC);
print_r($array);
?>

Przyk³ad jest niemal identyczny jak poprzedni. Jedyn¹ ró¿nic¹ jest to, ¿e

SQLite tworzy bazê w pamiêci serwera, co zasygnalizowaliœmy bazie po-
przez wprowadzenie do konstruktora parametru „:memory:”. Wraz z zakoñ-
czeniem tego skryptu ca³a baza zostanie bezpowrotnie usuniêta z pamiêci.

MySQL

W dziedzinie obs³ugi bazy danych MySQL dokona³o siê wiele powa¿-
nych zmian. W PHP5 do dyspozycji mamy teraz dwa rozszerzenia do
obs³ugi MySQL:

!

mysql, czyli stara proceduralna biblioteka do obs³ugi MySQL,

!

mysqli, czyli ca³kowicie nowa biblioteka obs³uguj¹ca zarówno
paradygmat obiektowy, jak i proceduralny, przeznaczona do pra-
cy z baz¹ MySQL 4.1 lub nowsz¹.

Nowoœci zwi¹zane z rozszerzeniem mysqli:

!

zapytania przygotowane (prepared statements),

!

mo¿liwoœæ wykonywania wielu zapytañ przy u¿yciu jednej funkcji
(multi-querying),

!

bezpieczne po³¹czenia przy u¿yciu SSL.

Instalacja mysqli

By zainstalowaæ rozszerzenie mysqli w œrodowisku Windows nale¿y:

1. OdnaleŸæ plik konfiguracyjny php.ini (ulokowany najczêœciej

w katalogu z instalacj¹ PHP) i edytowaæ go.

2. Poszukaæ sekcji: „Dynamic Extensions”, a nastêpnie linii:

„;extension=ext/php_mysqli.dll”.

3. Usun¹æ œrednik (znak komentarza) i zapisaæ plik.
4. Przekopiowaæ plik „libmysqli.dll” z g³ównego katalogu z instalacj¹

PHP do katalogu „system32” (najczêœciej c:\windows\system32\).

5. Zrestartowaæ/uruchomiæ serwer Apache.
6. Sprawdziæ za pomoc¹ funkcji phpinfo(), czy rozszerzenie zosta³o

poprawnie za³adowane (czy widnieje na liœcie zainstalowanych
rozszerzeñ).

mysqli

Nowa biblioteka do obs³ugi bazy MySQL to odpowiedŸ na wzrastaj¹ce mo¿-
liwoœci MySQL. G³ównymi zaletami nowego, udoskonalonego rozszerzenia
jest przede wszystkim wiêksza wydajnoœæ, nawet 40-krotnia w porównaniu ze
starym rozszerzeniem. Dzieje siê tak za spraw¹ przepisanego od nowa kodu.

Interesuj¹co prezentuj¹ siê te¿ mo¿liwoœci obiektowego interfejsu mysqli,

bowiem ka¿d¹ z trzech klas interfejsu mo¿na rozszerzaæ poprzez dziedzicze-
nie. Mo¿liwe jest te¿ stworzenie w³asnej, efektywniejszej obs³ugi b³êdów.

Jak zapewniaj¹ autorzy nowego rozszerzenia mysqli, tak¿e i bez-

pieczeñstwo uleg³o radykalnej zmianie. Stary system wymiany hase³
miêdzy baz¹ a klientem zosta³ przebudowany i jest odporny na ataki
niczym protokó³ SSH. Nie bez znaczenia dla bezpieczeñstwa jest tak¿e
mo¿liwoœæ tworzenia zapytañ przygotowanych. Utrudniaj¹ one znacz-
nie tworzenie ataków typu „SQL Injection” (wiêcej o typach ataków
w artykule „Bezpieczeñstwo PHP” – MI 2/2004).

PHP

INTERNET.listopad.2004

101

WARSZTAT

PROGRAMY

MAGAZYN

FIRMA

Z OK£ADKI

NEWSY

NA CD

"

background image

C

M

Y

K

Przejœcie z jednego rozszerzenia na drugie jest bardzo proste. Je¿eli

porównaæ interfejsy proceduralne obu rozszerzeñ, to s¹ one bardzo do
siebie zbli¿one:

<?php
$conn = mysqli_connect(’localhost’, ’user’,

!

’password’, ’test’);
if(!$conn)

die();

$query = mysqli_query($conn, ’SELECT a, b FROM

!

jakastabela ORDER BY id LIMIT 5’);
while($data = mysqli_fetch_assoc($query)) {

print_r($data);

}
echo mysqli_affected_rows($conn);
mysqli_close($conn);
?>

Jak ³atwo dostrzec, nowe rozszerzenie ró¿ni siê tylko symbolicznie.

Przejœcie ze starego na nowe powinno wiêc byæ ³atwe, o ile zadbamy o:

!

przemianowanie funkcji z mysql_ na mysqli_,

!

wstawienie uchwytu po³¹czenia jako parametru wymaganego.

Interfejs obiektowy

Przyjrzyjmy siê teraz przyk³adowi, który zrobi dok³adnie to samo, lecz
tym razem skorzystamy z interfejsu obiektowego:

<?php
$conn = new mysqli(’localhost’, ’user’,

!

’password’, ’test’);
if(!$conn)

die();

$query = $conn->query(’SELECT a, b FROM

!

jakastabela ORDER BY id LIMIT 5’);
while($data = $query->fetch_assoc()) {

print_r($data);

}
echo $conn->affected_rows;
$conn->close();
?>

W pierwszej kolejnoœci tworzymy nowy obiekt, podaj¹c mu za pa-

rametry wszystkie dane dotycz¹ce po³¹czenia. Nastêpnie wywo³ujemy
metodê query() i nie istnieje ju¿ potrzeba przekazywania uchwytu.
Przy metodzie fetch_assoc() nale¿y zwróciæ uwagê na to, ¿e operuje-
my ju¿ na zupe³nie innym obiekcie. Nie jest to, jak poprzednio, obiekt
$conn, lecz obiekt $query. W interfejsie obiektowym rozszerzenia my-
sqli dysponujemy bowiem trzema klasami:

!

klasa mysqli jest wykorzystywana do nawi¹zywania relacji miê-
dzy PHP ó MySQL,

!

klasa mysql_result pozwala na obs³ugê wyników (st¹d
fech_assoc(), korzysta z obiektu $query, utworzonego przez
metodê query() obiektu $conn),

!

klasa mysql_stmt dedykowana jest zapytaniom przygotowanym.

Przejœcie ze starego interfejsu proceduralnego na nowy interfejs

obiektowy bêdzie wymaga³o znacznie wiêcej pracy, ni¿ przejœcie ze
starego na nowy interfejs proceduralny. Dlatego te¿ interfejs obiekto-
wy przewidziany jest do stosowania w oprogramowaniu (skryptach)
pisanym ca³kowicie od nowa.

Zapytania przygotowane

Wraz z rozszerzeniem mysqli wprowadza siê pojêcie zapytania przy-
gotowanego, które do tej pory by³o nieznane programistom operuj¹-

PHP

INTERNET.listopad.2004

102

NA CD

NEWSY

Z OK£ADKI

FIRMA

MAGAZYN

PROGRAMY

WARSZTAT

!

KLASA

NAZWA

OPIS

ZWRACA

mysqli

affected_rows

właściwość zwraca ilość zmian dokonanych w rekordach

mixed

przy wykorzystaniu zapytań z rodziny INSERT, UPDATE lub DELETE.

mysqli

autocommit(bool tryb)

metoda włącza lub wyłącza auto−commit

bool

mysqli

close()

metoda zamyka połączenie z bazą

bool

mysqli

commit()

metoda zatwierdza bieżącą transakcję

bool

mysqli

connect(*)

metoda otwiera nowe połączenie z bazą danych

obiekt (połączenie)

mysqli

errno

właściwość zwraca kod błędu ostatniego błędnego zapytania

integer

mysqli

error

właściwość zwraca opis błędu dokonanego

string

w ostatnim błędnym zapytaniu

mysqli

field_count

właściwość zwraca ilość kolumn zwróconych

integer

przez ostatnie dokonane zapytanie

mysqli

info()

metoda dostarcza informacji o ostatnio wykonanym zapytaniu

string

mysqli

insert_id

właściwość zwraca ID ostatnio utworzonego rekordu

0 lub integer ID

mysqli

mysqli(*)

konstruktor klasy mysqli; parametry są opcjonalne

obiekt (połączenie)

mysqli

prepare (string zapytanie)

metoda przygotowuje zapytanie do wykonania

obiekt stmt lub fałsz (jeżeli błąd)

mysqli

query (string zapytanie [, int tryb_wyniku])

wykonuje zapytanie na bazie danych

prawda/obiekt lub fałsz (jeżeli błąd)

mysqli

rollback()

metoda cofa aktualną transakcję

bool

mysqli

select_db (string baza)

metoda zmienia/wybiera bazę danych

bool

mysqli_stmt

bind_param(object stmt, string

metoda przypisuje wartości do wskazanego

bool

typy, mixed &dane1 [, mixed &...]))

przygotowanego zapytania

mysqli_stmt

bind_result(object stmt, mixed

metoda przypisuje zmienne

bool

&dane1 [, mixed &...])

do przygotowanego zapytania

mysqli_stmt

close()

metoda zamyka przygotowane zapytanie

bool

mysqli_stmt

execute(object stmt)

metoda wykonuje przygotowane zapytanie

bool

mysqli_stmt

prepare (string zapytanie)

metoda przygotowuje zapytanie do wykonania

obiekt stmt lub fałsz (jeżeli błąd)

mysqli_result

fetch_array([int typ wyniku])

zwraca numeryczną, asocjacyjną lub numeryczną

tablica lub NULL

i asocjacyjną tablicę z wierszem wyników

mysqli_result

fetch_assoc()

zwraca tablicę asocjacyjną z wierszem wyników

tablica asocjacyjna lub NULL

mysqli_result

fetch_field()

na podstawie wyniku zapytania zwraca informację

obiekt lub fałsz

o kolejnej kolumnie w postaci obiektu

mysqli_result

fetch_fields()

ma podstawie wyniku zapytania zwraca informację

tablica obiektów lub fałsz

o kolumnach w postaci obiektu

mysqli_result

fetch_object()

zwraca wiersz wyników w postaci obiektu wypełnionego danymi

obiekt lub NULL

mysqli_result

fetch_row()

zwraca tablicę numeryczną z wierszem wyników

tablica lub NULL

mysqli_result

free()

czyści z pamięci dane związane z wynikiem

void

* – [string host [, string uzytkownik [, string haslo [, string baza [, int port [, string gniazdo]]]]]]

background image

cym na bazie MySQL, a doskonale znane u¿ywaj¹cym baz Oracle.
Idea tego rodzaju zapytañ jest prosta, a zarazem skuteczna. Przy ich
u¿yciu mo¿emy tworzyæ zapytania przygotowane oparte o praktycznie
wszystkie elementy jêzyka SQL. Najczêœciej z zapytañ przygotowa-
nych korzysta siê przy wprowadzaniu danych (INSERT), ich aktuali-
zacji (UPDATE), ale tak¿e przy pobieraniu (SELECT) i usuwaniu
(DELETE).

Gdy tworzymy zapytanie typu INSERT, do sekcji VALUES wpro-

wadzamy informacje, które chcemy dodaæ do tabeli. Podobne zapyta-
nie powtarzamy tyle razy, ile informacji mamy do dodania. Przy czym
za ka¿dym razem do sekcji VALUES wprowadzamy inne dane. Tak
podstêpujemy, gdy chcemy wprowadziæ jakieœ dane do bazy:

INSERT INTO jakastabela (a, b) VALUES (’abcd’, ’1.24’)
INSERT INTO jakastabela (a, b) VALUES (’efgh’, ’6.32’)

Gdybyœmy miejsca, które ulegaj¹ zmianie zast¹pili znakiem zapy-

tania, wygl¹da³oby to tak:

INSERT INTO jakastabela (a, b) VALUES (?, ?)

Zapytanie przygotowane jest to najogólniej mówi¹c szablon, do

którego póŸniej bêdziemy wprowadzali dane w miejsce znaków zapy-
tania. Powy¿szy przyk³ad wysy³amy do bazy danych MySQL, by mo-
g³a go sobie sprawdziæ na obecnoœæ b³êdów sk³adni i zapisaæ w spe-
cjalnym buforze. Z powrotem MySQL odda nam uchwyt do tego za-
pytania, byœmy go mogli póŸniej wykorzystaæ. Gdy zechcemy wpro-
wadziæ jakieœ dane do tabeli, wystarczy do bazy danych przes³aæ tylko
te dane, które wejd¹ w miejsce znaków zapytania.

Taka metoda dzia³ania daje spore korzyœci. Po pierwsze baza da-

nych nie musi za ka¿dym razem sprawdzaæ zapytania na obecnoœæ b³ê-
dów. Wystarczy, ¿e zrobi to raz, bo zapytanie siê nie zmienia. Zmianie
ulegaj¹ tylko te dane, które wprowadzamy za pomoc¹ znaków zapyta-
nia. Poniewa¿ dane te trafiaj¹ do bazy pozbawione pozosta³ej czêœci
zapytania, maj¹ mniejsz¹ objêtoœæ, a co za tym idzie mo¿na je przes³aæ
szybciej. Biblioteka mysqli przy wysy³aniu tych danych zoptymalizuje
je jeszcze odpowiednio, by jak najmniej zajmowa³y i jak najszybciej
dotar³y do bazy. Taki sposób wykonywania zapytañ cechuje siê ponad-
to zwiêkszonym bezpieczeñstwem. Mysqli samodzielnie zneutralizuje
znaki, które mog¹ byæ k³opotliwe, odci¹¿aj¹c programistê od tego obo-
wi¹zku.

Podsumowuj¹c: ogólna idea przemawiaj¹ca za stosowaniem zapy-

tañ przygotowanych to uzyskanie maksymalnego przyspieszenia przy
wykonywaniu serii zapytañ poprzez:

!

stworzenie szablonów zapytañ, które s¹ kompilowane i spraw-
dzane,

!

uzupe³nienie szablonów, co pozwala na nie przesy³anie pe³nego
zapytania, lecz tylko zmieniaj¹cych siê danych.

Efektem jest mniejsza iloœæ przes³anych danych pomiêdzy baz¹ da-

nych a klientem oraz wiêksza prêdkoœæ dzia³ania dziêki ju¿ skompilo-
wanym szablonom. Jak to wygl¹da na przyk³adzie kodu?

<?php
$conn = new mysqli(’localhost’, ’user’,

!

’password’, ’test’);
$dane[0][’a’] = ’wxyz’;
$dane[0][’b’] = 1.65;
$dane[1][’a’] = ’wxyz’;
$dane[1][’b’] = 1.65;
$stmt = $conn->prepare(’INSERT INTO

!

jakastabela (a, b) VALUES (?, ?)’);

foreach($dane as $d) {

$stmt->bind_param(’sd’, $d[’a’], $d[’b’]);
$stmt->execute();

}
?>

Dane, które mamy zamiar wprowadziæ do bazy danych, miesz-

cz¹ siê w tablicy $dane. W pierwszej kolejnoœci wykonujemy meto-
dê prepare(), która ma za zadanie przygotowaæ zapytanie do póŸ-
niejszego wykorzystania. Szablon posiada dwa znaki zapytania,
czyli o tyle¿ zmiennych zostanie uzupe³niony. Do przypisywania
parametrów zwi¹zanych s³u¿y metoda bind_param(). Drugi i ka¿dy
kolejny parametr oznaczaj¹ wartoœci, o które kolejno zostanie uzu-
pe³niony szablon w miejsce „?”. Pierwszy parametr to coœ nowego.
Definiuje on jakiego typu danych s¹ zmienne uzupe³niaj¹ce sza-
blon. Kolejne znaki odpowiadaj¹ typom danych kolejnych znaków
zapytania, czyli naszych zmiennych. Po co to wszystko? By biblio-
teka mysqli mog³a wybraæ najbardziej optymalny dla niej sposób
transmisji danych do bazy danych. Poszczególne litery t³umaczy siê
jako nastêpuj¹ce typy:

!

„i” – wszystkie typy INT,

!

„d” – DOUBLE i FLOAT,

!

„b” – BLOBy,

!

„s” – wszystkie pozosta³e typy.

Poniewa¿ pierwsza zmienna wprowadzana do tabeli jest ci¹giem

znaków, czyli stringiem, korzystamy z litery „s”. Skoro zaœ druga
zmienna to liczba zmiennoprzecinkowa, u¿ywamy litery „d”. Tak
powstaje pierwszy parametr metody bind_param(), czyli „sd”. Po
przypisaniu danych do zapytania mo¿na go wykonaæ za pomoc¹
metody execute(). W ten sposób pêtla wykona ³¹cznie dwa razy za-
pytanie, co spowoduje dodanie dwóch rekordów do bazy danych.
Przy czym nale¿y zwróciæ uwagê, ¿e pracujemy nie na klasie my-
sql, lecz na mysql_stmt. Moment w którym tworzymy obiekt tej
klasy to wywo³anie metody prepare(). Od tej linii kodu pracujemy
wy³¹cznie na obiekcie klasy mysql_stmt. Za³¹czona tabela prezen-
tuje wybrane metody i w³aœciwoœci wszystkich trzech klas do ob-
s³ugi MySQL.

Zapytania przygotowane – pobieranie wyników

Stworzenie zapytañ przygotowanych mo¿liwe jest równie¿ w przypad-
ku pobierania. Zobaczmy to na przyk³adzie pobierania danych przy
u¿yciu sk³adni polecenia SELECT:

PHP

INTERNET.listopad.2004

103

WARSZTAT

PROGRAMY

MAGAZYN

FIRMA

Z OK£ADKI

NEWSY

NA CD

"

C

M

Y

K

background image

C

M

Y

K

PHP

INTERNET.listopad.2004

104

NEWSY

Z OK£ADKI

FIRMA

MAGAZYN

PROGRAMY

WARSZTAT

!

NA CD

<?php
$conn = new mysqli(’localhost’, ’user’,

!

’password’, ’test’);
$stmt = $conn->prepare(’SELECT a, b FROM

!

jakastabela ORDER BY id’);
$stmt->execute();
$stmt->bind_result($a, $b);
while($stmt->fetch()) {

echo $a.$b;

}
$stmt->close();
?>

Przygotowujemy typowe zapytanie za pomoc¹ metody prepare().

Jak ³atwo zauwa¿yæ, zapytanie to nie posiada znaków „?”. Dlacze-
go? Poniewa¿ nie bêdzie posiada³o ¿adnych innych wariantów. To
z kolei oznacza, ¿e za ka¿dym razem bêdziemy pobierali dane przy
u¿yciu tego samego zapytania. Zapytanie przygotowane wykonuje-
my, czyli przekazujemy za pomoc¹ metody execute() do serwera.
Nowoœci¹ w stosunku poprzednich przyk³adów jest metoda bind_re-
sult(), u¿ywana niejako zamiast bind_param(). Jej parametry
($a, $b) to kolejne kolumny z zapytania. Wiersz wyniku pochodz¹cy
z kolumny o nazwie „a” zostanie przypisany do zmiennej $a, wiersz
„b” do zmiennej $b. Metoda close() s³u¿y do oczyszczenia pamiêci
bazy z informacji na temat wskazanego zapytania przygotowanego.
Warto u¿yæ tej funkcji, by odci¹¿yæ bazê mo¿liwie jak najprêdzej.
O ile nie ma to wielkiego znaczenia przy ma³ych serwisach interne-
towych, o tyle ju¿ œrednie serwisy mog¹ odczuæ nieznaczny wzrost
wydajnoœci bazy.

Transakcje

Kolejnym narzêdziem, z którego warto skorzystaæ, jest mo¿liwoœæ do-
konywania transakcji na bazie MySQL. Zasadê dzia³ania transakcji
t³umaczy siê na przyk³adzie konta bankowego, bo to najprostszy, a za-
razem najbardziej obrazowy przyk³ad. Za³ó¿my wiêc, ¿e dokonujemy
transakcji pieniêdzy pomiêdzy klientem „a” a klientem „b”. Gdy prze-
lewamy klientowi „b” jakaœ sumê pieniêdzy, klientowi „a” musimy j¹
odj¹æ. Punkt po punkcie wygl¹da to tak:

1 – dodaj klientowi „b” kwotê x przelan¹ przez klienta „a”,
2 – odejmij klientowi „a” kwotê x przelan¹ do klienta „b”.

Do zrealizowania takiej operacji bankowej potrzebujemy wiêc

dwóch zapytañ. Co siê stanie, gdy jedna z tych operacji siê nie powie-
dzie z jakichkolwiek przyczyn? Z pewnoœci¹ ktoœ na tym straci. Jak
wiêc to powinno wygl¹daæ? Gdy baza dokona realizacji punktu 1,
a nastêpnie punktu 2, przelew pieniêdzy uznaje siê za zakoñczony suk-
cesem. Lecz gdy coœ zawiedzie i jeden z punktów nie bêdzie móg³ zo-
staæ zrealizowany, baza danych cofnie ca³¹ operacjê. Tak¹ metodê
dzia³ania nazywamy transakcj¹. Jest to wiêc niepodzielny zbiór pole-
ceñ, które musz¹ zostaæ wykonane wszystkie naraz lub nie mo¿e zo-
staæ wykonane ¿adne z nich.

Spróbujmy wiêc teraz zrealizowaæ przyk³adow¹ transakcjê przy

u¿yciu biblioteki mysqli. Przed tym jednak ma³a uwaga. Transakcji nie
uda siê wykonaæ, gdy korzystamy z tabel typu ISAM lub MyISAM. Te
typy nie obs³uguj¹ transakcji. By wykonaæ transakcjê, typ tabeli mo¿e-
my zmieniæ np. na InnoDB, a zrobimy to nastêpuj¹cym poleceniem:

ALTER TABLE ”jakastabela” TYPE = INNODB

Do utworzenia najprostszej transakcji wykorzystuje siê trzy metody:

!

autocommit(), która ustawiona na fa³sz rozpoczyna transakcjê; jest
to wiêc ekwiwalent komendy BEGIN – rozpocznij transakcjê,

!

commit() to metoda, która zatwierdza prawid³owoœæ przeprowa-
dzonej transakcji – wszystko OK, transakcja zakoñczy³a siê suk-
cesem, zapomnij o niej,

!

rollback() cofa wszystkie zapytania, które zosta³y wykonane pod-
czas transakcji – uniewa¿nia transakcjê.

Zobaczmy wszystkie metody w akcji:

<?php
$conn = new mysqli(’localhost’, ’user’,

!

’password’, ’test’);
$conn->autocommit(false);
$a = $conn->query(’INSERT INTO jakastabela

!

(a, b) VALUES (”defg”, 1.32)’);
$b = $conn->query(’INSERT INTO jakastabela

!

(a, b) VALUES (”hijk”, 3.35)’);
$c = $conn->query(’INSERT INTO jakastabela

!

(a, b) VALUES (”lmno”, 2.97)’);
if($a & $b & $c) {

echo ’ok!’;
$conn->commit();

}
else {

echo ’b³¹d!’;
$conn->rollback();

}
?>

By rozpocz¹æ transakcjê, nale¿y wy³¹czyæ (!) metodê auto-com-

mit(), ustawiaj¹c j¹ na wartoœæ fa³sz. Nastêpnie mo¿emy ju¿ wykonaæ
interesuj¹ce nas zapytania w transakcji. By nieco u³atwiæ przyk³ad, do
ka¿dego wyniku metody query() przypisano jedn¹ zmienn¹. Jak wia-
domo, metoda query() zwraca prawdê, gdy zapytanie typu INSERT siê
powiedzie, a fa³sz, gdy nast¹pi jakiœ b³¹d. Mo¿emy dziêki temu spraw-
dziæ czy wszystkie zapytania zosta³y zrealizowane poprawnie, poprzez
wykonanie iloczynu logicznego wszystkich wyników. Je¿eli zosta³y
wykonane poprawnie, finalizujemy transakcjê. Zatwierdzenie transak-
cji nastêpuje poprzez wykonanie metody commit(). Gdy któreœ z zapy-
tañ zwróci b³¹d, zostanie wykonana metoda rollback(), która cofnie
wszystkie operacje dokonane pocz¹wszy od ustawienia metody auto-
-commit() na fa³sz.

Prawid³owo skonstruowana transakcja napisana w paradygmacie

obiektowym powinna byæ obs³ugiwana przez zaawansowane mechani-
zmy obs³ugi b³êdów dostêpne wraz z PHP5. O nich szerzej mówiliœmy
w pierwszej czêœci artyku³u (MI 9/2004).

Tworzenie własnych metod

Rozszerzanie funkcjonalnoœci interfejsu obiektowego mysqli jest jak
najbardziej mo¿liwe i wcale nie trudne do stworzenia. Za rozszerzanie
funkcjonalnoœci nale¿y rozumieæ mo¿liwoœæ utworzenia nowych funk-
cji, które zrealizuj¹ te bardziej kompleksowe zadania, z których jednak
korzystamy na tyle czêsto, by warto je by³o tworzyæ. Spójrzmy wiêc
na poni¿szy przyk³ad:

<?php
class my_mysqli extends mysqli
{
function array_id($id, $table) {
$query = sprintf(’SELECT * FROM %s WHERE

!

id = ”%d”’, $table, $id);
return $this->query($query)->fetch_assoc();
}
}

background image

$conn = new mysqli(’localhost’, ’user’,

!

’password’, ’test’);
print_r($conn->array_id(’21’, ’jakastabela’));
?>

W przyk³adzie rozszerzyliœmy klasê mysqli klas¹ my_mysqli.

Zawiera ona jedn¹ metodê utworzon¹ na nasze potrzeby. Metoda ta
– array_id() posiada dwa parametry wejœciowe, które nastêpnie trafiaj¹
do zapytania. Odpowiedzi¹ metody jest tablica asocjacyjna z wynika-
mi. Ostatnia linia przyk³adu demonstruje w jaki sposób mo¿emy póŸ-
niej skorzystaæ z utworzonej funkcji pomocniczej.

Podsumowanie

W pierwszym artykule z serii zosta³ omówiony nowy silnik Zend
Engine 2.0. Zainstalowaliœmy now¹ wersjê PHP5 na domowym ser-
werze, a nastêpnie poznaliœmy specyfikatory dostêpu, klasy i meto-
dy abstrakcyjne, interfejsy, s³owo kluczowe final, konstruktory
i destruktory, sta³e wewn¹trzklasowe, w³aœciwoœci i metody sta-
tyczne, w³aœciwoœæ instanceof, funkcjê __autoload(), przeci¹¿anie
metod, metody __get i __set, sta³¹ __METHOD__ oraz zagadnienia
zwi¹zane z przestrzeniami nazw. W drugiej czêœci artyku³u dokoñ-
czyliœmy pojêcia zwi¹zane z nowym silnikiem obiektowym. By³o
o klonowaniu obiektów oraz o zaawansowanym mechanizmie ob-

s³ugi wyj¹tków throw/try/catch. Druga czêœæ artyku³u w przewa¿a-
j¹cej czêœci obejmowa³a zagadnienia zwi¹zane z obs³ug¹ XML.
PHP5 zaimponowa³ now¹ bibliotek¹ do obs³ugi XML, Simple
XML, która jest rzeczywiœcie prosta w obs³udze. Powiedzieliœmy
o XPath w SimpleXML oraz o obs³udze RSS przez SimpleXML.
Nastêpny fragment artyku³u by³ opisem odœwie¿onej biblioteki
DOM, wraz z jej mo¿liwoœciami i problematyk¹. Tak dobrnêliœmy
do trzeciej czêœci, która skupi³a siê na obs³udze baz danych przez
PHP5. Zosta³ omówiony nowy, obiektowy interfejs MySQL o na-
zwie mysqli oraz interfejs obiektowy SQLite. Trzecia czêœæ artyku-
³u by³a ju¿ ostatni¹ czêœci¹ kursu wprowadzaj¹cego w nowoœci
zwi¹zane z pi¹t¹ ods³on¹ PHP i stanowi praktyczny komplet pod-
stawowych informacji na temat PHP5.

n

PRZYDATNE ODNOŚNIKI

http://php.net/mysqli

– oficjalna dokumentacja rozszerzenia MySQLi

– Improved MySQL Ext.

http://php.net/sqlite

– oficjalna dokumentacja biblioteki plikowej bazy

danych SQLite

http://dev.mysql.com/doc/mysql/en/Installing.html

– oficjalna dokumen−

tacja wyjaśniająca jak zainstalować bazę MySQL

PHP

INTERNET.listopad.2004

105

WARSZTAT

PROGRAMY

MAGAZYN

FIRMA

Z OK£ADKI

NEWSY

NA CD

"

C

M

Y

K

str_split()

Konwertuje ciąg znaków na tablicę numeryczną. Jako pierwszy parametr po−
dajemy ciąg znaków, który chcemy przekształcić na tablicę numeryczną.
Drugi, opcjonalny parametr to liczba, która ustala co ile znaków ma nastąpić
podzielenie ciągu znaków na elementy tablicy. Wartością domyślną parame−
tru drugiego jest 1. Oznacza to, że ciąg znaków zostanie zamieniony na tyle
elementów tablicy, ile znaków występuje w tym ciągu.

Sposób implementacji:

array str_split (string ci¹g_znaków

!

[, int szerokoœæ_ciêcia])

Przykład:

<?php

$string = ”Jakiœ tekst”;

$array1 = str_split($string);

print_r($array1);

$array2 = str_split($string, 4);

print_r($array2);

?>

Wynik:

Array

(

[0] => J

[1] => a

[2] => k

[3] => i

[4] => œ

[5] =>

[6] => t

[7] => e

[8] => k

[9] => s

[10] => t

)

Array

(

[0] => Jaki

[1] => œ te

[2] => kst

)

strpbrk()

Przeszukuje ciąg znaków, sprawdzając czy nie występuje w nim jeden ze
wskazanych jako parametr znaków. Jeżeli występuje, wyświetli ciąg znaków
począwszy od odnalezionego znaku. Gdy nie znajdzie w ciągu znaków żad−
nego z poszukiwanych znaków, zwróci fałsz.

Sposób implementacji:
string strpbrk (string stóg_siana, string lista_znaków)

Przykład:

<?php

$string = ’Jakiœ tekst’;

echo strpbrk($string, ’ ’);

echo strpbrk($string, ’ke’);

?>

Wynik:

tekst

kiœ tekst

time_nanosleep()

Opóźnia wykonanie programu o podaną ilość sekund i nanosekund. Infor−
macje te podaje się kolejno jako pierwszy i drugi parametr. W przypadku po−
wodzenia funkcja zwraca prawdę, w przypadku błędu zwraca fałsz.

Sposób implementacji:

mixed time_nanosleep (int sekundy, int nanosekundy)

Przykład:

<?php

time_nanosleep(0, 500000)

?>

Wynik: skrypt „zasypia” na pół sekundy.

Nowe funkcje w PHP5


Wyszukiwarka

Podobne podstrony:
PHP Co nowego Co nowego w piątej wersji PHP 02 2004
PHP cz 1 v2
Co nowego we wzmacniaczach mocy Nieznany
Co zakwasza a co odkwasza organizm, cz 1
Struktura organizacyjna cz 2 11 10
1466205 2100SRM0735 (11 2004) UK EN
Co nowego w wersji 50
Co nowego wniosła do Twojej wiedzy o?szyzmie lektura Rozmowy z Katem Kazimierza Moczarskiego
Rynek czynnik cz 1" 11 06
ogrody, Referat z antropologii-ogolny opis ogrodnictwa-25[1].11.2004, Referat z antropologii - 25
Pisma Świętego Starego i Nowego Testamentu cz 2
HTML hiperłącza 11 2004
11 2004 jak to dzialaid 12737 Nieznany (2)
Co zakwasza a co odkwasza organizm, cz 2
DGP 2015 01 20 co nowego w prawie antymonopolowym

więcej podobnych podstron