Documente Academic
Documente Profesional
Documente Cultură
Mysql 350 p-8
Mysql 350 p-8
Funcia f ormat_entry () nu este prezentat aici. n esen, este asemntoare cu funcia f ormat_rtf_entry () din
scriptul gen_cat, dar fr cuvintele de control RTF.
Publicarea pe Internet a catalogului Ligii istorice
n seciunea urmtoare, Utilizarea DBI n aplicaiile Web", vom ncepe s scriem scripturi care se conecteaz la
serverul MySQL pentru a extrage informaii i pentru a scrie acele informaii n forma paginilor Web care apar n
browserul Web al unui client. Aceste scripturi genereaz cod HTML n mod dinamic, n conformitate cu cerinele
clientului, nainte de a ajunge la acel punct, s ncepem s ne gndim la HTML insernd un program DBI care
genereaz un document HTML static, ce poate fi ncrcat n arborele cu documente al unui server Web. Un
candidat bun n acest sens este un catalog al Ligii istorice pe care l creai n format HTML, deoarece unul din
scopurile noastre era oricum publicarea pe Internet a catalogului.
n general, un document HTML are o structur care este oarecum asemntoare cu urmtoarea:
<HTML>
<HEAD>
<TITLE>Titlul paginii mele</TITLE>
</HEAD>
<BODY>
<H1>Titlu de nivel 1</H1>
... coninutul corpului documentului...
nceputul documentului nceputul capului documentului titlul documentului sfritul capului documentului
nceputul corpului documentului un titlu de nivel l
</BODY> * sfritul corpului documentului
</HTML> * sfritul documentului
Pentru a genera catalogul n acest format, nu este necesar s scriei un ntreg script. V reamintii c, atunci cnd
am scris scriptul gen_cat, am folosit un cadru extensibil astfel nct s putem insera programul pentru generarea
catalogului n formate suplimentare. Aceasta nseamn c, pentru a aduga programe pentru generarea de date de
ieire n format HTML, trebuie s scriem funciile de iniializare i curenie" a documentului, precum i o
funcie pentru formatarea intrrilor individuale. Apoi, trebuie s crem un element de tip cutie de distribuie"
care s indice spre aceste funcii. Schia de document prezentat anterior se poate mpri destul de simplu n
seciuni de prolog si epilog, care pot fi manipulate de funciile de iniializare, respectiv curenie, precum i ntr-
o parte de mijloc, care poate fi generat de funcia de formatare a intrrilor. Funcia de iniializare HTML
genereaz toate elementele documentului, pn la titlul de nivel l, iar funcia de curenie genereaz etichetele de
nchidere </BODY> i </HTML>:
sub html_init
prin "<HTML>\n";
Capitolul? Interfaa API pentru Perl DBI 351
prin "<HEAD>\n";
prin "<TlTLE>Catalogul membrilor Ligii istorice</TITLE>\n";
prin "</HEAD>\n";
prin "<BODY>\n";
prin "<H1>Catalogul membrilor Ligii istorice</H1>\n";
sub html_cleanup
{
prin "</BODY>\n"; prin "</HTML>\n";
}
Adevrata munc, de obicei, rezid n formatarea intrrilor. Dar nici mcar aceasta nu este prea grea. Putem
copia funcia format_rtf_entry(), ne asigurm c toate caracterele speciale din cadrul intrrii sunt codificate i
nlocuim cuvintele de control RTF cu etichetele de marcare HTML:
sub format_html_entry
{
my ($entry_ref) = shift;
my ($adresa);
# codeaza caracterele speciale din HTML foreach my $key (keys (%{entry_ref }))
$entry_ref ->{key} $entry_ref ->{key} = $entry_ref->{key} $entry_ref->{key} =
- s/&/&/g;
- s/\"/"/g;
- s/>/>/g;
- s//</g;
printf "<STRONG> Nume: %s</STRONG><BR>\n",
format_name ($entry_ref ) ; $adresa = " ";
$adresa .= $entry_ref->{strada} if $entry_ref ->{strada}; $adresa .= ", " . $entry_ref ->{oras} if $entry_ref-
>{oras}; $adresa .= ", " . $entry_ref->{stat} if $entry_ref ->{stat}; $adresa .= " " . $entry_ref ->{cod} if
$entry_ref ->{cod}; prin "Adresa: $adresa<BR>\n" if Sadresa; prin "Telefon: $entry_ref ->{telefon}<BR>\n"
if $entry_ref ->{telefon}; prin "Email: $entry_ref->{email}<BR>\n"
if $entry_ref ->{email}; prin "Interese: $entry_ref ->{interese}<BR>\n"
if $entry_ref ->{interese}; prin "</BR>n";
352 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Acum, vom aduga la cutia de distribuie un alt element, care indic spre funciile de scriere HTML, iar
modificrile aduse scriptului gen_cat au fost finalizate:
# cutie de distribuie care conine funcii de formatare
# pentru fiecare format al datelor de ieire my (%cutie_distributie) =
"banquet"
# funcii pentru lista de banchet
"init" => undef, # nu este necesara nici
# o iniializare
"entry" => \&format_banquet_entry, "cleanup" => undef # curenia nu este necesara
"rtf =>
# funcii pentru formatul RTF
"in it"
"entry"
"cleanup"
=> \&rtf_init,
=> \&format_rtf_entry,
=> \&rtf_cleanup
"html" =>
# funcii pentru formatul HTML
"init" => \&html_init,
"entry" => \&format_html_entry,
"cleanup" => \&html_cleanup
}
); . . -;i
Pentru a genera catalogul n format HTML, rulai urmtoarea comand i instalai l fiierul de ieire rezultant n
arborele cu documente al serverului dumneavoastr Web: l
% gen_cat html > catalog.html Cnd actualizai catalogul, putei rula comanda din nou, pentru a actualiza
versiunea! electronic a acestuia. O alt strategie este s configurai o sarcin a utilitarului cron care l s se
execute periodic. Astfel, catalogul n versiune electronic va fi actualizat automat. I De exemplu, pot folosi o
intrare crontab ca aceasta, pentru a rula gen_cat n fiecrei diminea la ora 4:
|
O 4 * * * /u/paul/samp_db/gen_cat > /usr/local/apache/htdocs/catalog.html! Utilizatorul n numele cruia
ruleaz aceast sarcin cron trebuie s aib att permisiuj| nea de a executa scripturile localizate n catalogul meu
samp_db, ct si permisiunea de al scrie fiiere n arborele cu documente al serverului Web.
',!
Capitolul 7 Interfaa APt pentru Perl DBI 353
Utilizarea DBI n aplicaii Web
Scripturile DBI pe care le-am scris pn acum au fost concepute pentru a fi utilizate din interpreter ntr-un mediu
bazat pe linii de comand, dar DBI este util i n alte contexte, cum ar fi n cazul dezvoltrii aplicaiilor bazate pe
Web. Cnd scriei scripturi DBI care pot fi invocate din browserul dumneavoastr Web, deschidei noi si
interesante posibiliti de a interaciona cu bazele dumneavoastr de date.
De exemplu, dac afiai date n format tabelar, putei transforma cu uurin fiecare titlu de coloan ntr-o
legtur (link), pe care o putei selecta pentru a sorta din nou datele din coloana respectiv. Aceasta v permite s
vizualizai datele ntr-un alt mod cu un singur clic, fr a introduce nici o interogare. Sau, putei furniza un
formular n care un utilizator poate introduce criterii pentru cutarea ntr-o baz de date, iar apoi afiai o pagin
care conine rezultatele cutrii. Funcionaliti simple ca aceasta pot avea un impact semnificativ asupra
nivelului de interactivitate pe care l furnizai pentru accesul la coninutul bazelor dumneavoastr de date. n
plus, de regul caracteristicile de afiare ale browserelor Web sunt superioare celor ale unei ferestre terminal,
deci datele de ieire arat i ele frecvent mai bine.
n aceast seciune, vom crea urmtoarele scripturi bazate pe Web:
Un browser general pentru tabelele din baza de date samp_db. Aceast aplicaie nu este legat de vreo operaie
specific pe care dorim s o efectum cu baza de date, dar ilustreaz numeroase concepte de programare n Web
i furnizeaz o modalitate convenabil de examinare a informaiilor pe care le conin tabelele.
Un browser de punctaje, care ne permite s examinm rezultatele obinute la orice test sau chestionar. Este un
mijloc rapid de examinare a rezultatelor de la evenimentele de tip examinare i este util atunci cnd trebuie s
stabilim curba rezultatelor la un test, astfel nct s putem acorda lucrrilor note de tip literal.
Un script pentru identificarea membrilor Ligii istorice care manifest interese comune. Aceast operaie se
poate realiza permind utilizatorului s introduc o expresie de cutare, iar apoi cutnd expresia respectiv n
cmpul interese al tabelului membru. Deja am scris un script n linie de comand care execut aceast operaie,
dar o versiune bazat pe Web furnizeaz un punct de referin instructiv, permind o comparaie ntre dou
abordri ale aceleiai sarcini.
Vom scrie aceste scripturi folosind modulul Perl CGLpm, care reprezint modalitatea cea mai simpl de a lega
scripturi DBI la Web. (Pentru instruciuni cu privire la procurarea modulului CGI.pm, vezi Anexa A.) Modulul
CGI.pm este astfel denumit deoarece v ajut s scriei scripturi care folosesc protocolul Common Gateway
Interface, care definete modul n care un server Web comunic cu alte programe. Modulul CGI.pm se ocup de
detaliile pe care le incumb un numr de operaii comune de ntreinere, cum ar fi colectarea valorilor
parametrilor transferai scriptului dumneavoastr de ctre serverul Web ca date de intrare. De asemenea, CGI.pm
furnizeaz metode convenabile de generare a datelor de ieire n format HTML, ceea ce reduce posibilitatea de a
scrie programe HTML cu malformaii n comparaie cu a scrie personal etichete HTML brute.
354 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Vei nva suficient de multe despre CGI.pm n capitolul de fa pentru a v scrie propriile dumneavoastr
aplicaii Web, dar, desigur, nu am descris toate funcionalitile sale. Pentru a nva mai multe despre acest
modul, consultai volumul Official Guide to Programming with CGI.pm, de Lincoln Stein (John Wiley, 1998)
sau examinai documentaia electronic la adresa:
http://stein.cshl.org/WWW/software/CGI/
Configurarea serverului Apache pentru scripturile CGI
n afar de DBI i CGI.pm, mai avem nevoie de nc o component pentru scrierea scripturilor bazate pe Web, i
anume un server Web. Instruciunile din aceast seciune sunt orientate n direcia utilizrii scripturilor cu
serverul Apache, dar probabil c putei folosi un alt server, dac dorii, printr-o oarecare adaptare a
instruciunilor.
Diferitele componente ale unei instalri a serverului Apache se gsesc, de obicei, n catalogul /usr/local/apache.
Pentru expunerea de fa, cele mai importante subcataloage ale acestui catalog sunt htdocs (pentru arborele de
documente HTML), cgi-bin (pentru scripturile executabile i programele care vor fi invocate de ctre serverul
Web) i conf (pentru fiierele de configurare). Aceste cataloage pot avea un alt amplasament pe sistemul
dumneavoastr, n acest caz, operai modificrile adecvate la notele care urmeaz.
Trebuie s v asigurai c cgi-bin nu se afl n interiorul arborelui de documente Apache, astfel nct scripturile
din cadrul su s nu poat fi solicitate sub form de text simplu. Aceasta este o msur de precauie. Nu dorii ca
programe client ru intenionate s v examineze scripturile n cutarea unor bree de securitate, prin aspirarea"
textului scripturilor si studierea acestuia.
Pentru a instala un script CGI n vederea utilizrii cu serverul Apache, inserai-1 n catalogul cgi-bin, dup care
transferai dreptul de proprietate a fiierului ctre utilizatorul pentru care ruleaz serverul Apache i modificai-i
modul astfel nct s fie executabil i s poat fi citit numai de ctr.e acel utilizator. De exemplu, dac serverul
Apache ruleaz ca un utilizator cu numele www, folosii urmtoarele comenzi:
% chown www nume_script
% chmod 500 nume_script Probabil c va trebui s rulai aceste comenzi ca www sau ca root. Dac nu avei
permisiunea de a instala scripturi n catalogul cgi-bin, putei cere administratorului de sistem si i efectueze
aceast operaie n numele dumneavoastr.
Dup ce scriptul a fost instalat, l putei solicita din browserul dumneavoastr expediindJ serverului Web adresa
URL adecvat, n mod caracteristic, adresa URL se prezint astfel:.]
http:/1 numele.gazdei.dv/cgi-binlnume_script
Solicitarea scriptului din browserul dumneavoastr de Web determin execuia acest de ctre serverul Web.
Datele de ieire ale scriptului v sunt trimise napoi, iar rezultat apare ca o pagin Web n browserul
dumneavoastr.
Dac dorii s folosii scripturi CGI cu mod_perl pentru a obine performane mai bunel iat ce avei de fcut:
Capitolul 7 Interfaa API pentru Perl DBI 355
1. Verificai dac dispunei cel puin de urmtoarele versiuni ale programelor necesare: Perl 5.004, CGI.pm 2.36
i modJDerl 1.07.
2. Asigurai-v c mod_perl este compilat n executabilul dumneavoastr Apache.
3. Configurai un catalog pentru stocarea scripturilor. Eu folosesc /usr/local/apache/cgi-perl. Catalogul cgi-perl
nu trebuie s se afle n interiorul arborelui de documente al serverului dumneavoastr Apache, din aceleai
motive de securitate ca i catalogul cgi-bin.
4. Cerei serverului Apache s asocieze scripturile care se gsesc n catalogul cgi-perl cu mod_perl:
Alias /cgi-perl/ /usr/local/apache/cgi-perl
<Location /cgi-perl>
SetHandler perl-script
PerlHandler Apache::Registry
Options ExecCGI </Location>
Dac folosii o versiune curent a serverului Apache care utilizeaz un singur fiier de configurare, plasai toate
aceste directive n fiierul httpd.conf. Dac versiunea dumneavoastr de Apache folosete abordarea mai veche
cu trei fiiere pentru informaia de configurare, plasai directiva Alias n fiierul srm.conf, respectiv liniile
Location n fiierul access.conf.
Nu activai directivele mod_perl, PerlSendHeader sau PerlSetupEnv pentru catalogul cgi-perl. Acestea sunt
manipulate automat de CGI.pm, iar activarea lor poate induce conflicte de prelucrare.
Adresa URL a unui script mod-perl este similar cu aceea a unui script CGI standard. Singura diferen este
aceea c specificai cgi-perl n loc de cgi-bin:
http://numele.gazdei. dv/cgi-perl/nume_script
Pentru mai multe informaii, vizitai regiunea mod_perl a sitului Web Apacl e, de la urmtoarea adres:
http://perl/apache/org/
O scurt introducere n CGI.pm
Pentru a scrie un script Perl care folosete modulul CGI.pm, plasai o linie use lng nceputul scriptului, apoi
creai un obiect CGI care v ofer acces la metodele si variabilele modulului CGI.pm:
use CGI;
my ($cgi) = new CGI;
Scripturile noastre CGI folosesc caracteristicile modulului CGI.pm prin invocarea metodelor utiliznd variabila
$cgi. De exemplu, pentru a genera un titlu de nivel l, vom folosi metoda h1 () astfel:
prin $cgi->h1 ("Titlul meu");
356 Partea a ll-a Utitizarea interfeelor de programare ale sistemului MySQL
De asemenea, CGI.pm accept un stil de utilizare care v permite s-i apelai, metodele ca funcii, fr
construcia iniial $cgi->. Nu folosesc aici sintaxa respectiv, deoarece notaia $cgi-> este mai asemntoare cu
modul de utilizare a modulului DBI, precum i . deoarece mpiedic apariia unor conflicte ntre numele
funciilor din modulul CGI.pm i numele oricror altor funcii pe care Ie definii.
Verificarea parametrilor de intrare i scrierea datelor de ieire
Una dintre operaiile pe care CGI.pm le execut automat este tratarea tuturor detaliilor urte" implicate n
colectarea informaiilor de intrare furnizate de serverul Web scrip-tului dumneavoastr. Pentru a obine acele
informaii, tot ce avei de fcut este s invocai metoda pa r am (). Putei obine numele tuturor parametrilor
disponibili astfel:
my (@param) = $cgi->param (); Pentru a regsi valoarea unui anumit parametru, denumii parametrul care v
intereseaz:
if (!$cgi->param ("parametruljneu"))
prin "parametruljneu nu este configurat\n" ;
else
printf "Valoarea parametrului parametruljneu: %s\n", $cgi->param ("parametruljneu");
De asemenea, CGI.pm furnizeaz metode pentru generarea datelor de ieire care trebuie trimise browserului
client. S considerm urmtorul document HTML:
<HTML>
<HEAD>
<TITLE>Titlul paginii mele</TITLE>
</HEAD>
<BODY>
<H1>Titlu de nivel 1</H1>
<P>Paragraf 1.
<P>Paragraf 2. %
</BODY>
</HTML> Acest program folosete $cgi pentru a produce un document echivalent:
prin $cgi->header ();
prin $cgi->start_htnrl (-title => "Titlul paginii mele");
prin $cgi->h1 ("Antetul paginii mele");
prin $cgi->p ();
prin "Paragraf 1.\n";
prin $cgi->p ();
prin "Paragraf 2.\n";
prin $cgi->end_html ();
Capitolul? Interfaa API pentru Perl DBI 357
Unul dintre avantajele utilizrii modulului CGLpm pentru generarea datelor de ieire n loc de a scrie personal
cod HTML brut sunt acelea c putei gndi n uniti logice, nu folosind etichete individuale de marcare, iar
codul dumneavoastr HTML are mai puine anse de a conine erori. (Motivul pentru care am spus c are mai
puine anse" este acela c CGI.pm nu v va mpiedica s facei lucruri bizare, cum ar fi includerea unei liste
ntr-un titlu.) De asemenea, pentru textele (altele dect etichetele) pe care le scriei, CGI.pm furnizeaz
modificarea automat a semnificaiei unor caractere (escaping) precum < sau >, care sunt speciale pentru HTML.
Utilizarea metodelor modulului CGI.pm de generare a datelor de ieire nu v mpiedic s scriei personal cod
HTML brut, dac dorii. Putei combina cele dou metode, combinnd apelurile la metodele CGI.pm cu
instruciuni de afiare care genereaz etichete literale.
Modificarea automat a semnificaiei textelor HTML si URL
Dac scriei texte - diferite de textele etichetelor - cu ajutorul mefoddor CGI.pm, precum start_html() sau ti1 (),
programul modific automat semnificaia caracterelor speciale din text. De exemplu, dac generai un titlu
folosind urmtoarea instruciune, caracterul & din textul titlului va fi convertit n & de ctre CGI.pm:
prin $cgi->strt_html {-title => "A, B & C");
Dac scriei texte - altele dect textele etichetelor - fr a folosi metoda modulului CGI.pm de generare a datelor
de ieire, probabil c trebuie s le trecei mai nti prin funcia escapeHTML(), pentru a v asigura c
semnificaia tuturor caracterelor speciale a fost modificat n mod corespunztor. Acest fapt este de asemenea
adevrat atunci cnd construii adrese URL care pot conine caraqtere speciale, dei, n acest caz, trebuie s
folosii n schimb metoda escape (). Este important s folosii metoda de codare adecvat, deoarece fiecare
metod trateaz diferite seturi de caractere drept caractere speciale si codific acele caractere speciale folosind
formate care difer unele de altele. S lum n considerare urmtorul script Perl scurt:
#! /usr/bin/perl
use CGI;
$cgi = new CGI;
$s = "x<= y, corect?";
prin $cgi->escapeHTML ($s) ."\n";
prin $cgi->escape ($s) ."\n";
# codificare pentru
# utilizare ca text HTML
# codificare pentru
# utilizare intr-un URL
Dac rulai acest script, va produce urmtoarele date de ieire, de unde putei observa c procedeul de codificare
pentru textul HTML nu este acelai ca n czu! adreselor URL:
x<=y, corect?
x%3C%3Dy%2C%20corect%3F
358 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL Scrierea paginilor cu utilizri
multiple
Unul din principalele motive pentru scrierea scripturilor bazate pe Web care genereaz cod HTML, n loc de a
scrie documente HTML statice, este acela c un script poate produce diferite categorii de pagini, n funcie de
modul n care este invocat. Toate scripturile CGI pe care le vom scrie au aceast proprietate. Fiecare din aceste
scripturi funcioneaz astfel:
1. Cnd solicitai pentru prima dat scriptul de la browserul dumneavoastr, acesta genereaz o pagin iniial,
care v permite s selectai tipul de informaie dorit.
2. Cnd efectuai o selecie, scriptul este re-invocat, dar de data aceasta regsete i afieaz ntr-o a doua pagin
informaiile specifice pe care le-ai solicitat.
Principala problem, n acest caz, este c dorii ca selecia pe care o efectuai din prima pagin s determine
coninutul celei de-a doua pagini, dar, n mod normal, paginile Web sunt independente unele de altele, dac nu
realizai unele aranjamente speciale. Trucul este de a determina scriptul s genereze pagini care atribuie unui
parametru o valoare care indic urmtoarei invocri a scriptului ceea ce dorii. Cnd invocai scriptul pentru
prima dat, parametrul nu are nici o valoare; acest fapt indic scriptului s prezinte pagina sa iniial. Cnd
indicai informaiile pe care dorii s le vedei, pagina invoc din nou scriptul, dar cu parametrul configurat la o
valoare care indic scriptului ce are de fcut.
Exist diferite moduri de transfer al instruciunilor de la o pagin napoi la un script. O modalitate este de a
furniza utilizatorului un formular pe care acesta s-1 completeze. Cnd utilizatorul trimite formularul, coninutul
formularului este trimis serverului Web. Serverul transmite informaiile scriptului, care poate afla datele trimise
de utilizator invocnd metoda param (). Astfel vom proceda pentru cel de-al treilea script CGI al nostru (cel care
per- mite utilizatorului s introduc un cuvnt cheie pentru a cuta n catalogul Ligii istorice). \
Un alt mod de specificare a instruciunilor ctre un script este de a transfera informaiile l ca parte a adresei URL
pe care o trimitei serverului Web atunci cnd solicitai scriptul. ] Astfel vom proceda pentru scripturile de
navigare n tabelele din baza de date samp_db, J respectiv de navigare prin tabelele cu punctaje. Aceast metod
se bazeaz pe faptul c l scriptul genereaz o pagin care conine hiperlegturi. Prin selectarea unei legturi se l
invoc din nou scriptul, dar se specific o valoare a parametrului care indic scriptului ce | are de fcut, n
schimb, scriptul se invoc singur n diferite moduri, pentru a furniza l diferite categorii de rezultate, n funcie de
legtura pe care o selecteaz utilizatorul. l
Un script i poate permite s se auto-invoce expediind browserului o pagin care conine l o hiperlegtur spre
propriul su URL. De exemplu, un script denumit scriptuljneu J poate scrie o pagin care s conin aceast
legtur: i
<A HREF="/cgi-bin/scriptul_meu">Clic pe mine!</A> J
Cnd utilizatorul execut clic pe textul Clic pe mine!", browserul utilizatorului trimitf i o cerere pentru
scriptuljneu napoi la serverul Web. Desigur, aceast aciune nu va fcea dect s determine scriptul s trimit
din nou aceeai pagin, deoarece nu au fost furnizatesl alte informaii. Totui, dac ataai un parametru la URL,
acel parametru este trimis napoi! serverului Web atunci cnd utilizatorul selecteaz legtura. Serverul invoc
scriptul, iaifl scriptul poate apela funcia param () pentru a detecta c parametrul a fost configurat sil poate
ntreprinde o aciune n funcie de valoarea parametrului. m
Capitolul 7 Interfaa API pentru Perl DBI 359
Pentru a ataa un parametru la sfritul adresei URL, adugai un caracter ? urmat de o pereche nume-valoare.
Pentru a ataa mai muli parametri, separai-i prin caractere &. De exemplu:
/cgi-bin/scriptul_meu?nume=valoare
/cgi-bin/scriptul_meu?nume=valoare&nume2=valoare2
Pentru a construi o adres URL cu parametri ataai care face referire la sine nsi, un script CGI trebuie s
nceap prin a apela metoda script_nane () pentru a-si obine propriul URL, iar apoi trebuie s ataeze parametri
la adres, astfel:
$url = $cgi->script_name (); # obine URL pentru script
$url .= "?nume=valoare"; # adaug primul parametru
$url .= "&nume2=valoare2"; # adaug al doilea parametru
Dup ce adresa URL a fost construit, putei genera o etichet de hiperlegtur <A> care conine adresa, folosind
metoda a() a modulului CGI.pm:
prin $cgi->a ({+href => $url}, "Clic pe minei");
Pentru a vedea mai limpede care este modul de funcionare al acestei metode, vom examina un scurt script CGI.
Cnd este invocat pentru prima dat, scriptul urmtor, denumit f lip_f lop, prezint o pagin denumit Pagina A,
care conine o singur hiperlegtur. Prin selectarea legturii scriptul va fi invocat din nou, dar parametrul pagina
este astfel configurat nct i indic s afieze pagina B. i pagina B conine o legtur cu scriptul, dar fr nici o
valoare pentru parametrul pagina. Ca atare, selectarea legturii n pagina B determin afiarea din nou a paginii
iniiale. Invocrile ulterioare ale scriptului determin afiarea alternativ a paginilor A si B.
use CGI;
my ($cgi) = new CGI;
my ($url) = $cgi->script_name (); # propriul URL al acestui script
print $cgi->header ();
if ($cgi->param ("pagina") ne "b") # afieaz pagina A
print $cgi->start_html (-title => "Flip-Flop: Pagina A"); prin "Aceasta este pagina A.<BR>Pentru a selecta
pagina B, "; $url .= "?pagina=b"; # ataeaz parametrul
# pentru a selecta pagina B print $cgi->a ({-href => $url}, "clic aici");
else # afieaz pagina B
print $cgi->start_html (-title => "Flip-Flop: Pagina B"); prin "Aceasta este pagina B.<BR>Pentru a selecta
pagina A, "; print $cgi->a ({-href => $url}, "clic aici");
prin $cgi->end_html();
360 Partea a It-a Utilizarea interfeelor de programare ale sistemului MySQL
Dac apare nc un client care solicit scriptul f lip_f lop, va fi prezentat pagina iniial, deoarece diferitele
browsere ale clienilor nu interacioneaz unele cu altele.
Valoarea variabilei $url a fost configurat ntr-o manier destul de cavalereasc" n exemplele precedente. Este
preferabil s folosii metoda escape () pentru a codifica numele i valorile parametrilor dumneavoastr atunci
cnd le ataai la un URL, n cazul n care conin caractere speciale. Iat o modalitate mai bun de a construi un
URL cu parametri ataai:
# obine URL pentru script
# adaug primul parametru $cgi->escape ("valoare"));
# adaug al doilea parametru
$url = $cgi->script_name () $url .= sprintf ("?%s=%s",
$cgi->escape ("nume"), $url .= sprintf ("&%s=%s",
$cgi->escape ("nume2"), $cgi->escape ("valoare2"));
Conectarea la serverul MySQL din scripturile Web
Scripturile n linie de comand pe care le-am prezentat n seciunea anterioar, Utilizarea DBI", foloseau un
preambul identic pentru stabilirea unei conexiuni cu serverul MySQL. Scripturile noastre CGI partajeaz si ele o
anumit parte de program, ns puin diferit:
use DBI;
use CGI;
use strict;
# Toi parametrii de conexiune prestabilii lipsesc
my ($host_name, $user_name, $password) = (undef, undef, undef); my (db_name) = "samp_db";
# construiete sursa de date
my ($dsn) = "DBI:mysql:$db_name";
$dsn .= ":hostname=$host_name" if $host_name;
$dsn .= ";mysql_read_default_file=/usr/local/apache/conf/samp_db.cnf";
# conectare la server
my (%attr) = ( RaiseError = 1 );
my ($dbh) = DBI->connect ($dsn, $user_name, Spassword, \%attr); Acest preambul difer de cel folosit
pentru scripturile n linie de comand din urm- j toarele motive:
Acum, prima seciune conine o instruciune use CGI.
Nu mai analizm argumentele din linia de comand.
Programul caut parametrii de conexiune ntr-un fiier cu opiuni, dar nu folosete fiie
. my. cnf din catalogul de baz al utilizatorului care ruleaz scriptul (cu alte cuvinte, cat^j logul de baz al
utilizatorului serverului Web). Serverul Web poate rula scripturi pent obinerea accesului la alte baze de date si
nu avem nici un motiv s presupunem c
CAPITOLUL o
Interfaa API pentru PHP
PHP este un limbaj de scripting ce v permite s scriei pagini Web care conin programe nglobate, programe ce
se execut la fiecare deschidere a paginii i care pot genera un coninut dinamic care va fi inclus ca parte a
datelor de ieire trimise browserului Web al unui client. Acest capitol descrie modul de utilizare a limbajului
PHP pentru a scrie aplicaii bazate pe Web care folosesc MySQL. Pentru o comparaie ntre PHP i interfeele
API pentru programarea n MySQL scrise n C, respectiv Perl DB, consultai capitolul 5, Introducere n
programarea MySQL".
Exemplele din capitolul de fa pornesc de la baza noastr de date demonstrativ, samp_db, folosind tabelele pe
care le-am creat pentru proiectul de eviden a rezultatelor colare i pentru Liga istoric n capitolul l,
Introducere n MySQL si SQL". Vom discuta despre PHP 3, dei PHP 4 se afl deja la versiunea beta n
momentul scrierii acestei cri i poate c va deveni deja disponibil pn cnd vei ajunge s citii rndurile de
fa. Compatibilitatea cu PHP 3 este unul dintre scopurile de proiectare specificate cu claritate ale versiunii PHP
4, deci aproape toate cele prezentate aici pentru PHP 3 sunt valabile i pentru PHP 4. Un set de note pentru
trecerea la PHP 4 descrie modificrile n raport cu PHP 3. Dac folosii PHP 4, trebuie s citii aceste note.
Acest capitol a fost scris pornind de la presupunerea c vei folosi PHP n conjuncie cu serverul Web Apache.
Biblioteca client pentru MySQL scris n C i fiierele antet trebuie s fie de asemenea instalate; aceste fiiere
sunt necesare atunci cnd construii PHP; n caz contrar, PHP nu va ti cum s obin accesul la bazele de date
MySQL. Dac trebuie s v procurai oricare dintre aceste programe, consultai Anexa A, Obinerea i
instalarea programelor". Instruciunile pentru obinerea scripturilor date ca exemplu, l create n acest capitol, se
gsesc de asemenea n anexa respectiv. Putei descrca scrip- l turile pentru a evita s le introducei personal de
la tastatur.
Sub UNIX, PHP se poate folosi cu Apache fie ca modul ncorporat care este legat n j fiierul binar executabil
Apache, fie ca interpreter autonom, folosit ca program CGli tradiional. Sub Windows, PHP poate rula numai ca
program autonom n momentul del fa, dei se lucreaz la dezvoltarea unui modul PHP 4 Apache, care va rula
sumj Windows NT.
n majoritatea cazurilor, acest capitol descrie funciile PHP numai n msura n care sunt necesare n expunere.
Pentru un listing mai comprehensiv al tuturor funciilor legate MySQL, vezi Anexa H, Referin API PHP". De
asemenea, probabil c vei dori consultai manualul PHP, care descrie gama complet de funcii pe care le
furnizeaz PHP, inclusiv funciile pentru utilizarea sistemelor de baze de date diferite de MySQI
Capitolul 8 Interfaa API pentru PHP 373
(PHP, ca si DBI, nu este constrns s funcioneze numai cu MySQL.) Manualul este disponibil din situl Web
PHP, la adresa http://www.php.net/. De asemenea, acest sit Web conine notele pentru trecerea de la PHP 3 la
PHP 4.
Caracteristicile scripturilor PHP
Numele fiierelor care conin scripturile PHP sunt scrise, n mod caracteristic, cu o extensie care permite
serverului dumneavoastr de Web s le recunoasc i s execute interpretorul PHP pentru a le prelucra. Dac
folosii o extensie care nu este recunoscut, scripturile dumneavoastr PHP vor fi servite n format text simplu.
Extensia folosit n acest capitol este .php. Alte extensii frecvent folosite sunt .php3 i .phtml. Pentru instruciuni
de configurare a serverului Apache astfel nct s recunoasc extensia pe care dorii s o folosii, consultai
Anexa A. Dac nu putei controla instalarea serverului Apache pe calculatorul dumneavoastr, aflai de la
administratorul de sistem care este extensia adecvat pentru a fi utilizat.
Noiuni fundamentale despre PHP
Funcia elementar a limbajului PHP este de a interpreta un script pentru a genera o pagin Web care este trimis
unui client, n mod caracteristic, scriptul conine o combinaie ntre coduri HTML, care sunt trimise literal
clientului, si linii de program PHP, care sunt executate ca program. Datele de ieire produse de program sunt
trimise clientului, indiferent de natura lor, deci clientul nu vede niciodat programul, ci numai datele de ieire
rezultante.
Cnd PHP ncepe s citeasc un fiier, pur i simplu copiaz tot ceea ce gsete acolo n datele de ieire, cu
presupunerea c fiierul conine HTML literal. Cnd interpretorul PHP ntlnete o eticheta special de
deschidere, comut din modul HTML n modul program PHP i ncepe s interpreteze fiierul drept linii de
program PHP care trebuie executate. Sfritul programului este indicat de o alt etichet special, moment n
care interpretorul comut napoi din modul program n modul HTML. Aceasta v permite s combinai un text
static (partea de HTML) cu rezultate generate dinamic (date de ieire ale programului din partea de PHP) pentru
a produce p pagin care variaz n funcie de circumstanele n care este apelat.
De exemplu, putei folosi un script PHP pentru a prelucra rezultatul unui formular n care un utilizator a introdus
parametri pentru o cutare ntr-o baz de date. Parametrii de cutare pot fi diferii pentru variante diferite de
completare a formularului, deci, arunci cnd scriptul execut cutri, fiecare pagin rezultant va reflecta o alt
cutare. S vedem cum funcione'az aceste procedeu, examinnd un script PHP extrem de simplu:
<HTML>
<BODY>
Salut, lume
</BODY>
</HTML>
Im-
374 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Acest script nu este foarte interesant, deoarece nu conine nici o linie de program PHP! La ce bun? vei ntreba.
Aceasta este o ntrebare logic. Rspunsul este c uneori este util configurarea unui script care conine numai
cadrul HTML pentru pagina pe care dorii s o generai, care apoi va fi adugat la liniile de program PHP. Este
un procedeu absolut corect i interpretorul PHP nu are nici o obiecie.
Pentru a include linii de program PHP ntr-un script, acestea se deosebesc de textul nconjurtor cu ajutorul a
dou etichete speciale, n spe ?php pentru a ncepe scriptul, respectiv ? pentru a-1 ncheia. Cnd interpretorul
PHP ntlnete eticheta de deschidere ?php, comut din modul HTML n modul program PHP si interpreteaz tot
ceea ce gsete drept linii de program PHP pn cnd vede eticheta de nchidere ?. Scriptul cuprins ntre cele
dou etichete este interpretat i nlocuit cu datele de ieire pe care le genereaz. Exemplul anterior poate fi scris
din nou, pentru a include un mic exemplu de program PHP, astfel:
<HTML>
<BODY>
<?php prin ("Salut, lume\n"); ?>
</BODY>
</HTML>
n acest caz, partea de program este redus la minimum, fiind alctuit dintr-o singur linie. Cnd programul este
interpretat, genereaz rezultatul Salut, lume, care devine parte a datelor de ieire trimise browserului clientului.
Astfel, pagina Web produs de acest script este similar celei produse n exemplul anterior, unde scriptul era
alctuit n totalitate din linii HTML.
Putei folosi linii de program PHP pentru a genera orice component a unei pagini Web. Deja am vzut una
dintre extreme, n care ntregul script era alctuit din HTML literal i nu coninea nici o linie de program PHP.
Cealalt extrem este un script alctuit n totalitate din linii de program PHP si care nu conine HTML literal:
<?php
prin ("<HTML>\n"); prin ("<BODY>\n"); prin ("Salut, lume\n"); prin ("</BODY>\n"); prin ("</HTML>\n');
Acest fapt demonstreaz c PHP v ofer o mare flexibilitate n ceea ce privete generarea! datelor de ieire.
PHP las la latitudinea dumneavoastr alegerea combinaiei celei adecvate ntre HTML i liniile de program
PHP. O alt dovad a flexibilitii limbajuk PHP const n aceea c nu este necesar s inserai toate liniile de
program ntr-un sing loc. Putei comuta ntre modul HTML si modul program PHP pe tot parcursul script lui,
oricum si oricnd dorii.
Capitolul 8 Interfaa API pentru PHP 375
Etichetele scripturilor PHP
n afar de etichetele folosite pentru exemplele din acest capitol, PHP nelege i alte etichete de script. Le putei
vedea n liniile de program PHP pe care le scriu alte persoane sau le putei folosi personal. PHP recunoate patru
stiluri de etichete:
Stilul de etichet prestabilit. Acesta este stilul pe care PHP este configurat s-l foloseasc n mod prestabilit:
<?php prin ("Salut, lume\n"); ?>
Stil cu etichet de deschidere scurt. Acesta este asemntor stilului prestabilit, cu excepia faptului c eticheta
de deschidere este mai scurt:
<? prin ("Salut, lume\n11); ?>
Stil compatibil ASP. Acest stil este comun n mediile Active Server Pages:
<% print ("Salut, lume\n"); %>
Stil de etichet SCRIPT. Acest stil este util dac folosii un editor HTML care nu agreeaz nici unul din
celelalte stiluri de etichete. Categoric se folosete mai mult text, dar stilul poate fi necesar cnd un editor nu v
accept programul PHP deoarece folosii alte stiluri de etichete:
<SCRIPT LANGUAGE="php"> prin ("Salut, lume\n"); </SCRIPT>
Stilul cu etichet de deschidere scurt i stilul compatibil ASP nu sunt activate n mod prestabilit. Pentru mai
multe instruciuni pentru activarea acestor etichete, consultai Anexa H.
Scripturi PHP autonome
Este posibil s scriei scripturi PHP autonome, pe care le putei invoca din linia de comand, aa cum procedai
cu un script de interpreter sau cu un script Perl, lat un exemplu:
#! /usr/local/bin/php -q
<?php prin ("Salut, lume\n"); ?>
Scriptul anterior poate fi denumit salut. php, poate deveni executabil folosind comanda chmod +x i poate fi
invocat din interpreter:
% salut.php
Salut, lume
n acest capitol nu vom scrie nici un script autonom. Toate exemplele au fost scrise pornind de la premisa c vor
fi invocate de ctre un server Web pentru a genera o pagin Web.
Scriptul urmtor este ceva mai substanial, dar relativ scurt, i prezint modul simplu n care putei obine acces
la o baz de date MySQL din PHP, respectiv modul n care putei folosi rezultatele unei interogri ntr-o pagin
Web. Scriptul urmtor a fost prezentat foarte succint n capitolul 5 si reprezint un fundament simplu al unei
pagini de baz a sitului Ligii istorice. Pe parcurs, vom aduga scriptului un plus de complexitate, dar, pentru
moment, nu face dect s afieze un scurt mesaj de salut si numrul actual al membrilor Ligii:
<HTML>
<HEAD>
<TITLE>Liga istorica americana</TITLE>
</HEAD>
Continuare
376 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Continuare
<BODY>
<P>Bine ai venit la situl Web al Ligii istorice.
<?php
$link = @mysql_pconnect ("pit-viper.snake.net", "paul", "secret")
or exit (); mysql_select_db ("samp_db")
or exit (); $result = mysql_query ("SELECT COUNT(*) FROM membru")
or exit (); if ($row = mysql_fetch_array ($result))
echo "<P>In prezent, Liga are " . $row[0] . " membri"; mysql_free_result ($result);
</BODY></HTML>
Mesajul de ntmpinare este numai un text static, deci cel mai uor este s-1 scriei pur i simplu sub form de
HTML literal. Pe de alt parte, numrul membrilor este dinamic i se modific n timp,'deci trebuie determinat
instantaneu prin interogarea tabelului membru din baza de date samp_db.
Textul programului delimitat de etichetele de deschidere i de nchidere a scriptului execut o operaie simpl.
Mai nti, deschide o conexiune cu serverul MySQL i transform samp_db n baz de date prestabilit. Apoi,
trimite o interogare serverului pentru a determina numrul de membri ai Ligii istorice din momentul respectiv
(pe care l evalum ca fiind numrul de rnduri din tabelul membru). Rezultatul interogrii este afiat ca parte a ,
unui mesaj care conine numrul de membri, iar apoi este eliminat.
Dac n orice moment al acestui proces se produce vreo eroare, scriptul i ncheie pur si simplu execuia. Nu
sunt generate nici un fel de date de ieire privind eroarea produsfl deoarece acestea pot fi derutante pentru cei
care viziteaz situl Web.1
S defalcm scriptul pe componente, pentru a vedea care este modul de funcionare an
fiecreia. Prima etap const n conectarea la server folosind funcia mysql_pconnect (yll
$link = @mysql_pconnect '("pit-viper.snake.net", "paul", "secret")
or exit ();
Funcia mysql_pconnect() preia ca argumente numele gazdei, numele utilizatorului sil parola si returneaz un
identificator de legtur n cazul n care conexiunea a fost sta-1 bilit cu succes, respectiv FALSE dac se
produce vreo eroare. Dac nu reuete ncercarel de conexiune, scriptul nostru apeleaz funcia exit (), care
termin imediat execuii scriptului, caz n care nu mai sunt generate alte date de ieire.
1 Dac generai ntreaga pagin Web prin intermediul liniilor de program PHP, oprirea programului caz de
eroare fr afiarea nici unor date de ieire i poate agasa pe cei care v citesc paginile, de unele browsere vor
afia o caset de dialog cu mesajul aceast pagin nu conine nici un fel de datc*| caset care trebuie eliminat. -
N.A.
Capitolul 8 Interfaa API pentru PHP 377
Dar ce nseamn caracterul din faa apelului la funcia mysql_pconnect() ? Acesta este caracterul Linite, v
rog". Unele funcii PHP scriu un mesaj de eroare n caz de eec, pe lng returnarea unui cod de stare, n cazul
funciei mysql_pconnect(), o ncercare ratat de conexiune determin apariia n pagina Web care este trimis
ctre browserul clientului a unui mesaj ca acesta:
Warning: MySQL Connection Failed: Access denied for user:
'paul@pit-viper.snake.net' (Using password: YES)2.
Asta nu-i frumos; persoana care ne viziteaz situl nu va ti cum s procedeze cu acest mesaj. Inseria caracterului
@ n faa apelului la funcia mysql_pconnect() elimin acest mesaj de eroare, astfel nct s putem alege singuri
modul de tratare a erorilor, pe baza valorii returnate. Pentru scriptul curent, cel mai bun lucru n cazul unei erori
este de a nu genera nici un fel de date de ieire legate de numrul membrilor, n acest caz, pagina va conine
numai mesajul de ntmpinare. ,.
Putei folosi caracterul @ cu orice funcie PHP> dar, dup experiena mea, apelul iniial la funcia
mysql_pconnect( )are cele mai mari anse s eueze; ca atare, exemplele din acest capitol elimin numai
mesajele generate de funcia respectiv.
Poate c nu v convine c numele i parola sunt nglobate n script, n vzul tuturor. Ar cam fi cazul... Este
adevrat c numele i parola nu apar n pagina Web care este transmis clientului, deoarece coninutul scriptului
este nlocuit de datele sale de ieire. Totui, dac serverul Web sufer o eroare de configurare si nu reuete s
recunoasc faptul c scriptul dumneavoastr trebuie prelucrat de PHP, va trimite scriptul sub form de text
simplu, iar parametrii dumneavoastr de conexiune vor fi expui. Vom aborda n curnd aceast problem, n
seciunea Utilizarea funciilor si a fiierelor include".
Identificatorul de legtur returnat de funcia mysql_pconnect () poate fi transferat ctre alte numeroase apeluri
la funcii conexe MySQL din interfaa API pentru PHP. Totui, pentru asemenea, apeluri, identificatorul este
ntotdeauna opional.
mysql_pconnect()sau mysql_connect()
O funcie care este similar cu mysql_pconnect () este mysql_connect (). Ambele preiau ca argumente numele de
gazd, numele utilizatorului i parola i ambele returneaz FALSE pentru a indica reuita sau eecul ncercrii de
conexiune. Diferena dintre cele dou apeluri este c mysql_pcon-nect () stabilete o conexiune persistent, n
timp ce mysql_connect () stabilete o conexiune non-persistent. O conexiune persistent difer de o conexiune
non-persistent n sensul c prima nu este nchis la terminarea scriptului. Dac un alt script PHP este executat
ulterior de acelai proces Apache copil i apeleaz funcia mysql_pconnect () cu aceleai argumente, conexiunea
este refolosit. Acest procedeu este cu mult mai eficient dect stabilirea fiecrei conexiuni pornind de la zero.
De exemplu, putei apela mysql_select_db() folosind oricare din urmtoarele forme: mysql_select_db
($db_name, $link); mysql_select_db ($db_name);
2 n traducere Avertisment: conexiune MySQL ratat: accesul interzis pentru utilizatorul... (Folosete parol:
DA). - N.T.
378 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Dac omitei argumentul link din orice apel PHP legat de MySQL care preia un asemenea argument, apelul
folosete conexiunea deschis cel mai recent. Astfel, dac scriptul' dumneavoastr deschide numai o singur
conexiune, nu trebuie s specificai niciodat n mod explicit un argument link n nici unul din apelurile
dumneavoastr MySQL - conexiunea respectiv va fi cea prestabilit. Situaia este complet diferit de
programarea n MySQL folosind interfeele API n C sau DBI, pentru care nu exist o asemenea valoare
prestabilit.
Am scris programul de conexiune n scriptul nostru de creare a unei pagini de baz simple dup cum se poate
vedea mai jos, pentru a clarifica tipul de valoare returnat de funcia mysql_pconnect():
$link = @mysql_pconnect ("pit-viper.snake.net", "paul", "secret")
or exit ();
Totui, nu folosim parametrul $link nicieri n cadrul scriptului, deci programul ar fi putut fi scris mai simplu
astfel:
@mysql_pconnect ("pit-viper.snake.net", "paul", "secret")
or exit ();
Presupunnd c stabilirea conexiunii a reuit, urmtoarea etap este selectarea unei baze de date:
mysql_select_db ("samp_db-)
or exit {);
Dac apelul la funcia mysql_select_db() eueaz, scriptul i ncheie execuia n tcere. O eroare este
improbabil n acest moment, dac am reuit s ne conectm la server i dac baza de date exist, dar este
prudent s verificm apariia eventualelor probleme i s lum msurile adecvate. Dup ce ai selectat baza de
date, putem trimite interogarea spre server, extragem rezultatul, l afim i eliberm memoria alocat setului de
rezultate: $result = mysql_query ("SELECT COUNT(*) FROM membru")
or exit (); if ($row = mysql_fetch_array ($result))
echo "<P>In prezent, Liga are " . $row[0] . " membri"; mysql_free_result ($result);
Funcia mysql_query() trimite interogarea la server pentru a fi executat. Interogarea nitJ trebuie s se termine cu
un caracter punct i virgul i nici cu grupul de caractere \q?'. Funcia mysql_query() returneaz FALSE dac
interogarea a fost ilegal sau dac nu ^\ putut fi executat dintr-un motiv oarecare, n caz contrar, returneaz un
identificator s setului de rezultate. Acest identificator este o valoare pe care o putem folosi pentru obine
informaii despre setul de rezultate. Pentru interogarea noastr, setul de rezultai | const dintr-un singur rnd cu
o singur valoare din coloan, reprezentnd numrul membri. Pentru a obine aceast valoare, transferm
identificatorul setului de rezultat funciei mysql_fetch_array() pentru a prelua rndul, atribuim rndul variabilei
$row sil obinem accesul la primul element (care se ntmpl s fie si singurul) sub forma $row[0].f
Cnd am terminat cu setul de rezultate, eliberm memoria alocat acestuia transferndu-funciei mysql_f
ree_result(). De fapt, acest apel nu este necesar n scriptul nost deoarece PHP elibereaz automat memoria
alocat tuturor seturilor de rezultate active l terminarea execuiei unui script.
Capitolul 8 Interfaa API pentru PHP 379
Funcia mysql_free_result() este util mai ales n scripturile care execut interogri foarte mari sau un numr
mare de interogri i previne utilizarea unei cantiti excesive de memorie.
Pentru a folosi scriptul nostru, trebuie s-1 instalm undeva, n acest capitol, am adoptat convenia prin care Liga
istoric american i are propriul su catalog, denumit lisua3, situat la nivelul cel mai de sus al arborelui de
documente Apache, deci scriptul paginii de baz poate fi instalat sub forma lisua/index.php n arborele respectiv.
Vom crea scripturi si pentru proiectul de eviden a rezultatelor colare, deci i vom atribui acestuia catalogul
evid. Dac gazda silului Web este pit-viper.snake.net, paginile din aceste dou cataloage au adrese URL care
ncep astfel:
http://pit - viper.snake.net/lisua/
http://pit-viper.snake.net/evid/
De exemplu, paginile de baz din fiecare catalog pot fi denumite index. php i pot fi accesibile astfel:
http://pit-viper.snake.net/lisua/index.php
http://pit-viper.snake.net/evid/index.php
Utilizarea funciilor i a fiierelor include
Scripturile PHP difer de scripturile DBI, prin aceea c scripturile PHP sunt localizate n arborele cu documente
al serverului dumneavoastr de Web, n timp ce scripturile DBI se gsesc, n mod caracteristic, ntr-un catalog
cgi-bin care se afl n afara arborelui cu documente. Astfel, apare o problem de securitate: o eroare de
configurare a serverului poate determina afiarea accidental pentru clieni, sub form de text simplu, a paginilor
localizate n arborele cu documente. Aceasta nseamn c numele de utilizator i parolele pentru stabilirea
conexiunilor cu serverul MySQL sunt ntr-un pericol mai mare de a fi expuse lumii exterioare dac sunt folosite
ntr-un script PHP dect dac se folosesc ntr-un script DBI.
Variabile n PHP
n PHP putei declara variabile prin simpla utilizare a acestora. Scriptul nostru de creare a unei pagini de baz
folosete trei variabile, i anume $link, $result i $row, din care nici una nu este declarat nicieri. (Exist
contexte n care trebuie s declarai variabilele, cum ar fi atunci cnd facei referire la o variabil global n
interiorul unei funcii, dar despre aceasta vom discuta ulterior.)
Variabilele sunt simbolizate printr-un identificator precedat de simbolul dolarului ($). Aceast notaie este
valabil indiferent de valoarea pe care o reprezint variabila, dei pentru tablouri i obiecte trebuie s mai
adugai i alte elemente pentru a obine accesul la elementele individuale ale unei valori. Dac o variabil $x
reprezint o singur valoare, cum ar fi un numr sau un ir, se poate obine acces la aceasta sub forma $x. Dac
$x reprezint un tablou cu indici numerici, elementele sale sunt accesibile sub forma $x[O], $x[ 1 ] etc. Dac $x
reprezint un tablou cu indici asociativi precum "galben" sau "mare", elementele sale sunt accesibile sub forma
$x [' galben" ] sau $x [" mare" J.
Tablourile PHP pot ayea att elemente numerice, ct i elemente asociative. De exemplu, att $x [ 1 ] ct i $x ["
m re" ] pot reprezenta elemente ale aceluiai tablou. Dac $x reprezint un obiect, are proprieti care sunt
accesibile sub forma $x-nume_proprietate. De exemplu, $x-galben i $x-mare pot fi proprieti ale variabilei $x.
Numerele nu se pot folosi ca nume de proprieti, deci $x-1 nu este o construcie corect n PHP.
' Abreviere personal pentru Liga Istoric a Statelor Unite ale Americii. - N.T.
380 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Scriptul nostru iniial pentru construcia paginii de baz a Ligii istorice este expus la aceast problem, deoarece
conine valorile literale ale numelui de utilizator si ale parolei MySQL. S mutm aceti parametri de conexiune
n afara scriptului, folosind dou dintre caracteristicile limbajului PHP: funcii i fiiere include. Vom scrie o
funcie samp_db_connect () pentru a stabili conexiunea, respectiv vom plasa funcia mr-un fiier include - un
fiier care nu face pane din scriptul nostru principal, dar la care se poate face referire din acesta. Unele avantaje
ale aceste abordri sunt:
Programul de stabilire a conexiunii este mai uor de scris. Nu avem nevoie s scriem toi parametrii i putem
cere funciei samp_db_connect () s selecteze baza de date automat dup conectare, astfel nct o funcie s
execute atribuiile a dou funcii PHP. Astfel, scripturile devin mai uor de neles, deoarece atenia
dumneavoastr se poate concentra asupra aspectelor caracteristice ale scriptului, fr a fi deturnat de programul
de configurare a conexiunii.
Fiierul include este accesibil din scriptul nostru, dar poate fi deplasat n afara arborelui cu documente Apache.
Ca atare, coninutul su devine inaccesibil clienilor i acetia nu mai pot avea acces la parametrii de conexiune,
chiar dac serverul Web sufer o eroare de configurare. Utilizarea unui fiier include este o bun strategie pentru
ascunderea oricror categorii de informaii importante, care nu dorii s fie trimise n afara sitului de ctre
serverul dumneavoastr de Web.
Aceasta nu nseamn, totui, c numele si parola sunt sigure din toate punctele de vedere. Utilizatorii care pot
deschide o sesiune de lucru la gazda serverului Web pot fi capabili s citeasc fiierul include n mod direct, dac
nu luai nici o msur de precauie. Consultai seciunea Conectarea la serverul MySQL din scripturile Web" din
capitolul 7, Interfaa API pentru Perl DBI" i reinei msurile de precauie descrise acolo pentru instalarea
fiierelor de configurare DBI astfel nct acestea s fie protejate de ali utilizatori. Aceleai msuri de precauie
se aplic i n cazul utilizrii fiierelor < include din PHP.
Influente lingvistice n PHP
Dac avei experien cu programarea n C, probabil ai observat c numeroase construcii sintactice din j scriptul
nostru sunt foarte similare celor pe care le folosii pentru programarea n C. De fapt, sintaxa PHfH deriv n mare
msur din C, deci asemnarea nu este o coinciden. Dac avei oarecare cunotine de Cv \ le vei putea
transfera n mare msur n PHP. De fapt, dac nu suntei sigur cu privire la modul de scriegf | a unei expresii sau
structuri de control n PHP, ncercai s o scriei n C i este posibil s fie corect. 1f
Dei PHP deriv cu precdere din C, sunt prezente i elemente de Java i Perl. Putei constata acest lucrtf ] din
sintaxa comentariilor, care permite oricare din urmtoarele trei forme:
# Comentariu in stil Perl.de la # pana la sfritul liniei
// Comentariu in stil C++ sau Java, de la // pana la sfritul liniei
/* Comentariu in stil C, intre slash-stea pana la sea-slash */
Alte asemnri cu Perl includ operatorul . de concatenare a irurilor (inclusiv .= drept operator de i catenare
aditiv), precum i modalitatea n care referinele la variabile i secvenele escape sunt in pretate n interiorul
ghilimelelor duble, dar nu i n interiorul ghilimelelor simple.
Capitolul 8 Interfaa API pentru PHP 381
Fiierul include poate fi folosit n mai multe scripturi. Astfel este promovat reutilizarea programelor, iar liniile
de program devin mai uor de ntreinut. De asemenea, permite efectuarea cu uurin de modificri globale n
fiecare script care obine acces la fiier. De exemplu, dac mutm baza de date samp_db de la pit-viper la boa, nu
trebuie s modificm o mulime de scripturi individuale, ci numai argumentul numele gazdei" din apelul la
funcia mysql_pconnect() din fiierul include care conine funcia samp_db().
Pentru a folosi fiiere include, trebuie s avei unde s le punei i trebuie s cerei limbajului PHP s le caute.
Dac sistemul dumneavoastr dispune deja de o asemenea locaie, o putei folosi. Dac nu, folosii urmtoarea
procedur pentru a stabili o locaie a fiierului include:
1. Creai un catalog n care vei stoca fiierele PHP include. Acest catalog nu trebuie s se afle n interiorul
arborelui cu documente al serverului Web! Eu folosesc un catalog include pentru PHP /usr/local/apache/php, care
se afl la acelai nivel ca i arborele meu cu documente (/usr/local/apache/htdocs), dar nu n interiorul acestuia.
2. Creai referine la fiierele include cu numele complet al cii de acces sau indicai limbajului PHP cataloagele
n care s le caute. Ultima metod este mai convenabil, deoarece, dac folosim numele de baz al fiierului,
PHP l va gsi automat.4 Pentru a indica limbajului PHP unde s caute, modificai fiierul de iniializare PHP
(/usr/local/lib/php3.ini n sistemul meu) pentru a schimba valoarea parametrului include_path. Dac acesta nu are
nici o valoare, atribuii-i calea de acces complet a noului catalog include:
include_path = "/usr/local/apache/php"
Dac include_path are deja o valoare, adugai noul catalog la valoarea respectiv: include_path =
"valoare_curenta:/usr/local/apache/php"
3. Creai fiierul include pe care dorii s-1 folosii si inserai-1 n catalogul include. Fiierul trebuie s aib un
nume distinctiv; pentru noi, numele samp_db. inc este suficient. Coninutul fiierului este prezentat n listingul
urmtor. Pentru scripturile pe care le scriem aici, cnd ne conectm la serverul MySQL, vom folosi ntotdeauna
baza de date samp_db, deci funcia de conexiune samp_db_connect () poate selecta automat acea baz de date.
Funcia returneaz un identificator de legtur dac reuete s se conecteze i dac selecteaz baza de date,
respectiv FALSE dac se produce vreo eroare. Funcia nu afieaz nici un mesaj dac se produce o eroare, ceea
ce permite apelantului s-i ncheie discret execuia sau s afieze un mesaj, n funcie de circumstane:
<?php
# samp_db.inc
# funciile comune ale bazei de date demonstrative samp_db
# se conecteaz cu serverul MySQL folosind numele si parola
# noastr ultrasecrete function sarop_db_connect ()
Continuare
[ Fiierele include dii? PHP sunt oarecum asemntoare cu fiierele antet din C, inclusiv sub aspectul c PHP le
va cuta n numeroase cataloage, exact aa cum pre-procesorul C caut fiierele antet C n mai multe cataloage. -
N.A.
382 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Continuare
i
$link = @my sql_pconnect(" pit -viper. snake. net ", "paul", "secret"); if (Slink && mysql_select_db
("samp_db"))
return ($link); return (FALSE);
Observai c fiierul samp_db.inc este delimitat prin etichetele Ophp si ?>. Aceasta deoarece PHP ncepe citirea
fiierelor include n modul HTML Fr etichete, PHP va trimite fiierul ca text simplu, fr a-1 interpreta drept
program PHP. Dac intenionai s includei cod HTML literal n fiier, nici o problem. Dar, dac fiierul conine
linii de program PHP, trebuie s delimitai codul folosind etichetele de script.
4. Pentru a face referire la un fiier dintr-un script, folosii o linie a aceasta: include ("samp_db.inc") ;
Cnd PHP vede linia respectiv, caut fiierul i i citete coninutul. Toate componentele fiierului devin
accesibile pentru componentele urmtoare ale scriptului.
Dup ce am configurat fiierul nostru include samp_db . inc, puten modifica pagina de baz a Ligii istorice astfel
nct s fac referire la fiierul includea s se conecteze la serverul MySQL apelnd funcia samp_db_connect( ):
<HTML>
<HEAD>
<TITLE>Liga istorica americana</TITLE>
</HEAD>
<BODY>
<P>Bine ai venit in situl Web al Ligii istorice.
<?php
include ("samp_db.inc");
samp_db_connect ( )
or exit () ; $result = mysql_query ("SELECT COUNT(*) FROM membru")
or exit () ; if ($row = mysql_fetch_array ($result))
include () sau require ()
PHP are o funcionalitate require ( ) care este similar cu include ( ) . Owebirea ntre ele este < n cazul funciei
include ( ) , fiierul este citit i evaluat la fiecare execuie a iistruciunii include ( ) . l cazul funciei require (),
fiierul este prelucrat o singur dat (de fapt, cottutul fiierului nlocuie instruciunea require ()). Aceasta
nseamn c, dac dorii s citii un alt fijir de fiecare dat cnd i executai programul sau avei un ciclu care
parcurge un set de fiiere, avtinevoie de include (J deoarece putei configura o variabil cu numele fiierului pe
care dorii s-l iridei i s folosii vri la ca argument al funciei include ( ) .
lHji&^M'.-t:V-,-u^-::^xai',;;.-,,^.,VX,_
r
echo "<p>in prezent, Liga are mysql_free_result ($result);
Capitolul 8 Interfaa API pentru PHP " . $row[0] . " membri";
383
</BODY></HTML>
Poate credei c nu am economisit un numr chiar att de mare de linii de program n pagina de baz folosind un
fiier include. Ateptai puin... Fiierul samp_db.inc va fi util i pentru alte funcii si l putem folosi ca un
depozit convenabil pentru diverse alte lucruri. De fapt, mai putem crea chiar acum alte dou funcii care vor fi
inserate n fiierul respectiv. Fiecare script pe care l scriem va genera un set oarecum stereotip de etichete
HTML la nceputul paginii, respectiv un alt set la sfritul acesteia, n loc de a le scrie literal n fiecare script,
putem scrie funcii html_begin ( ) si html_end ( ) care scriu etichetele automat. Funcia html_begin() poate
prelua dou argumente, care specific titlul paginii si antetul acesteia. Codul pentru cele dou funcii se prezint
astfel:
# Scrie etichetele HTML iniiale pentru pagina. Se presupune
# ca eventualele caractere speciale din variabilele $titlu si
# $antet, daca exista, sunt codificate in mod corespunztor.
function html_begin ($titlu, $antet)
{
prin ("<HTML>\n"); prin ("<HEAD>\n"); if (Stitlu)
prin ( "<TITLE>$titlu*/TITLE>\n" ) ; prin ("</HEAD>\n"); prin ("<BODY>\n"); if ($antet)
prin ("<H2>$antet</H2>\n");
# scrie etichetele HTML finale ale paginii.
function html_end ()
{
prin ("</BODY></HTML>\n");
}
Apoi, putem modifica pagina de baz a Ligii istorice astfel nct s foloseasc cele dou noi funcii si s aib ca
atare urmtorul aspect:
<?php
include ( " samp_db . inc " ) ;
$titlu = "Liga istorica americana";
html_begin ($titlu, $titlu);
?>
Continuare
384 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Continuare
<P>Bine ai venit in situl Web al Ligii istorice.
<?php samp_db_connect ()
or exit (); $result = mysql_query ("SELECT COUNT(*) FROM membru")
or exit (); if ($row = mysql_fetch_array ($result))
echo "<P>In prezent, Liga are " . $row[0] . " membri"; mysql_free_result ($result);
html_end ();
?>
Observai c programul a fost mprit n dou componente, iar textul HTML literal al mesajului de ntmpinare
este inserat ntre cele dou pri.
Utilizarea funciilor pentru generarea componentelor iniial i final ale paginii ne ofer o posibilitate
important. Dac dorim s modificm aspectul antetului sau al subsolului tuturor paginilor care folosesc aceste
funcii, putem include pur i simplu n funcii unele linii de program. Fiecare script care va folosi funciile va fi
automat afectat. De exemplu, putei dori s scriei un mesaj Drepturile de autor rezervate LISUA" n partea de
jos a fiecrei pagini din situl Web al Ligii istorice. O funcie de final de pagin, cum este html_end (), constituie
o modalitate simpl de a face aceast schimbare.
O pagin cu o interogare simpl
Scriptul pe care 1-am nglobat n pagina de baz a silului Ligii istorice ruleaz o interogare , care returneaz un
singur rnd. Urmtorul nostru script prezint modul de prelucrare a \ unui set de rezultate compus din mai multe
linii. Scriptul preia i afieaz coninutul tabelu- ] lui membru. Acesta este echivalentul PHP al scriptului DBI
dumpjnembers pe care 1-am creatj n capitolul 7, deci l vom denumi dumpjnembers. php. Acest script este
diferit de versiunea i DBI prin aceea c este destinat utilizrii ntr-un mediu Web, nu de la linia de comand.
Din\| acest motiv, trebuie s produc date de ieire n format HTML, nu doar s scrie un simplul text delimitat
prin tabulatori. Pentru a alinia n mod estetic liniile si coloanele, vom seriei nregistrrile membrilor ntr-un tabel
HTML. Scriptul se prezint astfel:
<?php
# dumpjnembers.php - afieaz lista membrilor Ligii istorice
include ("sampjdb.inc");
$titlu = "Lista membrilor Ligii istorice americane"; html_begin (Stitlu, $titlu);
sampjdb_connect ()
or die ("Nu se poate conecta la server");
Capitolul 8 Interfaa API pentru PHP 385
# emite interogarea
Squery = "SELECT nume, prenume, sufix, email,"
. "strada, ora, stat, cod_postal, telefon"
. "FROM membru ORDER BY nume"; $result = mysql_query ($query)
or die ("Nu poate executa interogarea");
prin ("<TABLE>\n");
# citete rezultatele interogrii, apoi face curenie while ($row = mysql_fetch_row ($result))
{
prin ("<TR>\n");
for ($i = 0; $i < mysql_num_fields (Sresult); $i++)
{
# modifica semnificaia caracterelor speciale si afieaz printf ("<TD>%s</TD>\n", htmlspecialchars ($row(i]));
}
prin ("</TR>\n");
}
mysql_free_result ($result);
prin ("</TABLE>\n");
html_end ();
?>
Acest script folosete funcia die() pentru a afia un mesaj si pentru a termina execuia scriptului dac se produce
vreo eroare.5 Aceasta este o alt modalitate de tratare a erorilor dect aceea folosit n pagina de baz a Ligii
istorice, unde execuia scriptului s-a ncheiat n tcere, n scriptul dumpjnembers.php, ne ateptm s vedem un
anumit rezultat, deci este logic s afim un mesaj de eroare prin care se indic apariia unei probleme.
Scriptul poate fi instalat n catalogul lisua si este accesibil sub forma http://pi.t-
viper.snake.net/lisua/dump_members.php. Apoi, putem aduga o legtur la noul nostru script n pagina de baz
a Ligii istorice, astfel nct publicul s fie la curent cu acesta:
<?php
include ("samp_db.inc");
$titlu = "Liga istorica americana"; html_begin ($titlu, $titlu);
<P>Bine ai venit la situl Web al Ligii istorice.
Continuare
1 Funcia die () este similar cu funcia exit (), dar afieaz un mesaj nainte de a-i ncheia execuia. - N.A.
386 Partea a ll-a Utilizarea interfeelor de programare ale sistemului MySQL
Continuare <?php samp_db_connect ()
or exit (); $result = mysql_query ("SELECT COUNT(*) FROM membru")
or exit (); if ($row = mysql_fetch_array ($result))
echo "<P>In prezent, Liga are " . $row[0] . " membri"; mysql_free_result (Sresult);
Putei consulta catalogul cu membri <A HREF="dump_members.php">aici</A>.
<?php html_end ();
else {
printf ("numrul de rnduri returnate: %d\n" mysql_num_rows (Sresult));
Continuare