Documente Academic
Documente Profesional
Documente Cultură
1. Introducere MySql.
a. Ce este mySQL?
b. Argumente in favoarea mySQL
c. Instalare
d. Instalare sub Windows
e. Rulare sub Windows
f. Instalare sub Linux
g. Testarea instalarii
2. Algebra Relationala. Proiectarea si crearea unei baze de date
a. Proiectarea unei baze de date
b. Crearea unui dictionar de date
c. Elemente de Algebra Relationala
d. Normalizarea unei baze de date
e. Crearea/Stergerea/Migrarea unei BD mySQL
3. Conectarea la serverul mySQL
a. Conectarea la serverul mySQL
b. Folosirea unui client tip linie de comanda
c. Verificarea conectarii si a starii serverului
d. Crearea si utilizarea unei baze de date
e. Crearea unei baze de date
f. Utilizarea unei baze de date
4. Tipuri de date. Tabele
a. Tipuri de date
b. Constante, identificatori, comentarii
c. Operator i si functii mySql
d. Creare si stergerea tabelelor
5. Gestiunea Accesului
a. Sistemul de Privilegii mySql
b. Proiectarea unui sistem de gestiune a accesului
c. Accesul concurent la date
d. Replicarea datelor
6. Gestionarea datelor.
a. Inserarea datelor in tabele
b. Comanda INSERT
c. Utilizare comenzii INSERT
d. Modificarea datelor din tabele
e. Comanda UPDATE
f. Utilizarea comenzii UPDATE
g. Stergerea datelor din tabele
h. Comanda DELETE
i. Utilizarea comenzii DELETE
7. Interogari
a. Interogarea datelor
b. Comanda SELECT
c. Utilizarea conditiilor de selectie
d. Ordonarea rezultatului
e. Folosirea alias-urilor (poreclelor)
8. Interogari avansate
a. Selectarea datelor din mai multe tabele. Operatia JOIN.
b. Selectarea datelor din mai multe tabele.
c. Tipuri de JOIN.
d. Extragerea informatiilor de sumarizare
9. Biblioteci mySQL. Accesul concurent la date.
a. Implemetarea programelor client.
b. Suport ODBC.
c. Suport JDBC.
d. Biblioteca MySQL C.
e. Suport Pearl.
f. Suport PHP.
g. Accesul concurent la date.
h. Tranzactii. Blocarea/deblocarea unei tabele.
i. Replicarea datelor.
10. Limbajul PHP
a. Introducere
b. Comparatia cu alte sisteme
11. PHP - Instalare
a. Instalarea serverului Apache
b. Instalarea suportului PHP pentru serverul Apache
c. Testarea instalarii modulului de PHP
d. Instalarea mySQL
e. Informatii aditionale
12. Tipuri de date. Variabile
a. Inserarea codului PHP intr-o pagina HTML. Taguri PHP
b. Generarea dinamica de continut HTML
c. Tipuri de date. Conversii de tip
d. Identificatori. Constante
e. Variabile utilizator. Variabile referinta. Domeniu de valabilitate
f. Accesarea variabilelor din form-uri HTML
13. Operatori si expresii
a. Operatori aritmetici
b. Operatori pe siruri de caractere
c. Operatori de asignare
d. Operatori de referire
e. Operatori de comparare
f. Operatori logici
g. Operatori pe biti
h. Operatori aditionali
i. Expresii
ABD
1. Introducere
1.1. Ce este mySQL?
MySQL este unul dintre cele mai populare sisteme de gestiune de baze de date (SGBD) in
regim OpenSource.
Producatorul sau se numeste MySQL AB si este o companie a carei principala activitate
consta in oferirea de servicii legate de acest SGBD.
Cele mai importante caracteristici ale MySQL sunt:
l
Este un SGBD.
Asigura gestiunea unei colectii structurate de date.
Este un SGBD relational.
Datele sunt organizate in tabele. Intre tabele sunt stabilite relatii si constrangeri de
integritate. Pentru gestiunea datelor foloseste limbajul SQL (Structured Query
Language) care este un standard in acest domeniu.
Este un sistem client -server.
Serverul de baze de date este separat logic si deseori fizic (pe calculatoare diferite)
de programele client care asigura interfata operatiilor cu baza de date. Serverul
MySQL suporta o paleta larga de programe client, scrise in diverse limbaje de
programare.
Este distribuit in formula Open Source Software.
Aceasta formula permite oricarei persoane sa utilizeze si sa modifice programul, care
poate fi luat gratuit de pe Internet. Formula utilizata pentru licentiere este GPL (GNU
General Public License). Pentru mai multe informatii accesati site-ul
http://www.gnu.org.
Este rapid.
In multe aplicatii este chiar mai rapid dacat alte sisteme foarte scumpe.
Este fiabil.
Asigura o buna protectie a datelor prin mecanisme specifice.
Este usor de utilizat.
Chiar daca ofera o paleta foarte bogata de functii, organizarea acestora si modul in
care au fost create faciliteaza folosirea lor.
Bazat pe fire de executie nucleu.
ABD
2. Instalare
2.1. Instalare sub Windows
Pentru instalare se vor urma pasii:
1. Download fisier mysql-3.23.xx-win.zip de la adresa www.mysql.com/downloads. De
preferabil se va aduce versiunea 45 (xx=45) sau mai noua, dar in varianta Stable
Release. Diferenta intre subversiuni consta doar in mici cosmetizari si inlaturare de
erori.
2. Dezarhivare fisier mysql-3.23.xx-win.zip intr-un director temporar (ex c:\temp). Daca
nu aveti instalat un program de dezarhivare puteti lua WinZip sau WinRar gratuit de
la adresa http://tucows.dnttm.ro
3. Se va rula programul setup.exe din directorul de dezarhivare.
4. Directorul de instalare va fi intotdeauna C:\mysql. In cazul in care, din diverse motive,
se doreste instalarea in alt director, se va instala in cel implicit si se va muta ulterior
cu ajutorul Windows Explorer. Daca s-a mutat, spre exemplu, in directorul
D:\progr\mysql, pornirea programului se va face cu comanda:
D:\progr\mysql\bin\mysqld --basedir D:\progr\mysql
5. Crearea fisierului de configurare se va face prin copierea fisierului my-example.cnf din
directorul de instalare in radacina discului C sub numele c:\my.cnf.
6. Daca dupa instalare s-a schimbat directorul, se vor activa liniile (prin stergerea
marcajului "#")
#basedir = d:/mysql/
#datadir = d:/mysql/data/
si se va inlocui referinta d:/mysql cu directorul unde a fost mutat programul.
ABD
c:\mysql\bin\mysqld
sau
c:\mysql\bin\mysqld -opt
Eventualele mesaje de eroare vor fi gasite in fisierul c:\mysql\mysql.err.
Pentru oprirea serverului se va tasta:
c:\mysql\bin\mysqladmin -u root shutdown
Sub Winodws NT/2000 se va instala serverul ca si serviciu (va fi disponibil automat chiar si
dupa repornirea sistemului) tastand comanda:
c:\mysql\bin\mysqld -nt -install
Pentru activarea serverului se va tasta in linia de comanda (Command Prompt):
NET START mysql
respectiv, pentru oprire:
NET STOP mysql
ABD
7. Crearea tabelelor implicite:
scripts/mysql_install_db
c:\mysql\bin\mysqlshow
ABD
N-upletul este un ansamblu de constituanti (X1, X2, , XN) sau de date (a1, a2,
, an) cu ai in dom(X i). Un N-uplet de constituanti poate fi considerat ca si un
constituant compus.
O relatie N-ara R(X) se defineste prin trei elemente:
1. precizarea unui N-uplet de constituanti (X1, X2, , XN);
2. definirea domeniului pentru fiecare constituant X i ;
ABD
3. definirea unui predicat logic care pentru orice N-uplet de date (a1, a2, ,
an) cu a i in dom(Xi ) cu i de la 1 la N da o propozitie adevarata sau falsa.
Relatia R(X) este formata din ansamblul N-upletilor pentru care predicatul da
propozitii adevarate.
Gradul unei relatii este dat de numarul atributelor ce formeaza relatia.
Principalele caracteristici ale unei relatii sunt:
l
l
O relatie este definita ca un set de N-upleti distincti (din acest punct de vedere
corespunde tipului algebric multime).
Se numeste supercheie (SK) un grup de atribute care identifica n mod unic un
N-uplet al relatiei. Exista relatii care au o singura supercheie formata din toate
atributele.
Se numeste cheie a relatiei R o supercheie minima, cu proprietatea ca,
nlocuind sau stergnd orice atribut din ea, se obtine un grup de atribute care nu
este supercheie pentru relatia data. Multimea cheilor unei relatii formeaza cheile
candidat din care trebuie aleasa o cheie primara.
Cheia primara (PK - primary key) este o cheie aleasa de administratorul bazei
de date pentru a identifica nregistrarile. De obicei se pe acest post se alege o
cheie cu un numar minim de atribute, daca este posibil chiar un singur atribut. La
nevoie se poate introduce o codifcare suplimentara fata de datele initiale ale
problemei.
Se numeste cheie externa (FK - foreign key) un grup de atribute care constituie
o cheie primara ntr-o alta relatie. O cheie externa ajuta la legarea datelor din cele
doua relatii.
Pentru prelucrarea datelor din tabele teoria relationala defineste doua tipuri de
operatori: operatori din teoria multimilor - UNION, INTERSECT, DIFERENCE,
KHARTEZIAN PRODCT, respectiv operatori specifici algebrei relationale:
SELECT, PROJECT, UNION. Acesti operatori stau la baza limbajelor de
interogare relationale, dintre care cel mai cunoscut este SQL.
ABD
11
ABD
Varianta: nu se permit atribute care nu fac parte din cheile candidat ale relatiei si
care determina alte atribute.
Se poate da si o definitie generalizata pentru forma 3NF. Orice atribut al relatiei
ndeplineste:
l
l
O varianta mai restrictiva este BCNF - Boyce Codd Normal Form. O relatie este
n BCNF daca, pentru orice dependenta X->Y din R, X este o cheie candidat a lui
R.
Forma normala 4 (4NF) cere:
l relatia R sa fie n 3NF sau BCNF
l R nu are dependente multivaloare
Relatia R(A,B,C) contine o dependenta multivaloare daca:
l
l
l
l
A
A
A
B
12
ABD
In general cel mai important criteriu ramane totusi spatiul pe disc. Chiar daca in
zilele noastre discurile au capacitati foarte mari, o baza de date cu redundanta
mare, pe langa ca ocupa inutil foarte mult spatiu, este si foarte greu de accesat
(viteza de cautare in tabele este in general proportionala cu dimensiunea
acesteia, daca nu sunt luate in considerare fisierele index).
3.1. Crearea unui dictionar de date
In urma procesului de proiectare in general va trebui intocmita o documentatie
pentru implementare.
Cea mai utilizata forma este aceea de Dictionar de Date.
Un dictioanar de date cuprinde:
l
l
13
Tip
Constrangeri
Comentarii
BD
buletin
caracter(8)
cheie primara
nume
prenumele
data_n
data nasterii
data
14
ABD
ABD
Interogarile se vor termina cu ';'. Ele se pot despartii pe mai multe linii prin apasarea tastei
ENTER. Ultima linie trebuie sa se termine cu ';'.
Limbajul de interogare nu este de tip "case sensitive", deci nu tine cont de litere mari/mici.
Practic se poate utiliza orice combinatie de litere mari sau mici.
ABD
17
ABD
18
ABD
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Numar intreg foarte mic. Intervalul de valori posibile este [-128..127]. Daca
se specifica UNSIGNED intervalul este [0..255].
SMALLINT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg mic. Intervalul de valori posibile este [-32768..32767]. Daca se
specifica UNSIGNED intervalul este [0...65535].
MEDIUMINT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg mediu. Intervalul de valori posibile este [-8388608..8388607].
Daca se specifica UNSIGNED intervalul este [0..16777215].
INT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg normal. Intervalul de valori posibile este [2147483648..2147483647]. Daca se specifica UNSIGNED intervalul este
[0..4294967295].
INTEGER [(M)] [UNSIGNED] [ZEROFILL]
Sinonim cu INT.
BIGINT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg mare. Intervalul de valori posibile este [9223372036854775808..9223372036854775807]! Daca se specifica
UNSIGNED intervalul este [0..18446744073709551615].
FLOAT [(M, D) [ZEROFILL]
Numar in virgula flotanta simpla precizie (numar real). Intervalul de valori
posibile este [-3.402823466E+38.. -1.175494351E-38, 0, 1.175494351E38..3.402823466E+38].
DOUBLE [(M, D) [ZEROFILL]
Numar in virgula flotanta dubla precizie. Intervalul de valori posibile este [1.7976931348623157E+308..-2.2250738585072014E-308, 0,
2.2250738585072014E-308..1.7976931348623157E+308].
REAL [(M, D) [ZEROFILL]
Sinonim cu DOUBLE.
DECIMAL [(M [, D]) [ZEROFILL]
Numar in virgula flotanta neinpachetat. Spre deosebire de tipurile
precedente, la care valorile sunt stocate binar, acesta retine valorile
numerice ca si siruri de cifre ASCII. Daca D lipseste, numarul va fi intreg.
Daca si M lipseste, numarul va fi pe maxim 10 cifre zecimale.
NUMERIC [(M [, D]) [ZEROFILL]
Sinonim cu DECIMAL.
19
ABD
1. DATE
2.
3.
4.
5.
Data calendaristica. Intervalul de valori posibile este ['1000-01-01'..'999912-31']. Stocarea/afisarea se face implicit in formatul 'YYYY-MM-DD' (anluna-zi).
DATETIME
Combinatie de data calendaristica si timp. Intervalul de valori posibile este
['1000-01-01 00:00:00'..'9999-12-31 23:59:59']. Stocarea/afisarea se face
implicit in formatul 'YYYY-MM-DD HH:MM:SS' (an-luna-zi
ora:minut:secunda).
TIMESTAMP [(M)]
Moment de timp. Include si data calendaristica. Este util la inregistrarea
efectuarii unor operatii gen inserare sau modificare pentru ca retine implicit
data efectuarii ultimei operatii. Doar prima coloana de acest tip din tabela in
care se face modificarea va fi actualizata automat! Intervalul de valori
posibile este ['1970-01-01 00:00:00'..'2037-01-01 00:00:00']. MySQL
afiseaza valorile TIMESTAMP in format YYYYMMDDHHMMSS,
YYMMDDHHMMSS, YYYYMMDD sau YYMMDD dupa cum M este 14 (sau
lipseste), 12, 8 sau 6. Parametrul M nu influenteza insa reprezentarea
interna a datelor la stocare.
TIME
Moment de timp. Intervalul de valori posibile este [-838:59:59'..'838:59:59'].
Reprezentarea este in format 'HH:MM:SS' (ora:minut:secunda). Motivul
pentru care ora nu este limitata la intervalul [0..24] esta ca acest tip poate fi
folosit si pentru a retine intervale de timp intre doua evenimente. Tot din
acest motiv ora poate fi si negativa.
YEAR [(2|4)]
An calendaristic pe 2 sau 4 cifre. Intervalul de valori posibile este
[1901..2155] pentru 4 cifre, respectiv [1970..2069] pentru 2 cifre (70-99..0069).
20
ABD
TINYTEXT
Valori BLOB, respectiv TEXT cu lungime de max. 255 elemente.
2. BLOB
TEXT
Valori BLOB, respectiv TEXT cu lungime de max. 65535 (64 KB) elemente.
3. MEDIUMBLOB
MEDIUMTEXT
Valori BLOB, respectiv TEXT cu lungime de max. 16777215 (16 MB)
elemente.
4. LONGBLOB
LONGTEXT
Valori BLOB, respectiv TEXT cu lungime de max. 4294967295 (4 TB)
elemente.
21
ABD
'constnta sir'
"alta constanta sir"
In interiorul unui sir se pot include caractere speciale precedate de semnul
'\' (escape):
\n Trecere la linie noua (new line).
\t Tab (caracter de aliniere).
\r Salt la inceputul liniei (carriage return).
\b Sterge inapoi.
\' Caracterul '.
\" Caracterul ".
\\ Caracterul \.
\% Caracterul '%'. Se poate folosi pentru a cauta caracterul %, in
conditiile in care acest caracter este folosit in expresii regulate
(subiectul va fi detaliat ulterior).
\_ Caracterul _. Se poate folosi pentru a cauta caracterul _, in conditiile
in care acest caracter este folosit in expresii regulate (subiectul va fi
detaliat ulterior).
Rulati secventele:
Activitate 1
2.2. Identificatori
Numele pentru baza de date, tabele, coloane, indecsi sau alias-uri trebuie sa
indeplineasca conditiile normale pentru identificatori in limabje de programare: sa
fie o combinatie de litere, cifre si semne grafice care incep cu o litera. In plus
mySQL impune:
Identificator
Baza de date
Tabela
Coloana
Alias
22
Semnificatie
ABD
Referinta la coloana unei tabele din baza de date activa. Se
poate folosi daca interogarea nu contine si alte tabele care
au coloane cu nume identice
Referinta explicita la coloana tabelei specificate prin
nume_tabela.nume_coloana
nume_tabela din baza de date activa.
Referinta explicita la coloana tabelei specificate prin
nume_BD.nume_tabela.nume_coloana nume_tabela din baza de date specificata prin nume_BD
(nu este necesar sa fie cea activa).
nume_coloana
Identificatorii pot fi scrisi in general cu orice combinatie de litere mari sau mici.
Pentru numele bazei de date si cel al tabelelor unele, implementari impun
respectarea tipului de caractere folosit la definirea elementelor respective. Ca si
regula generala, este bine sa se pastreze o conventie de notare care sa nu fie
schimbata de la o interogare la alta. O regula simpla este sa se scrie comenzile
SQL cu litere mari si identificatorii definiti de utilizator cu litere mici.
2.3. Comentarii
MySQL suporta trei tipuri de comentarii prin care se poate explica codul. Ele
sunt:
l
Activitate 2
ABD
mysql> SELECT (1+2)*3;
+ pentru adunare;
- pentru scadere;
* pentru inmultire;
/ pentru impartire; daca se imparte la 0 rezultatul va fi NULL;
Rulati secventele:
mysql> SELECT 3+5, 3-5;
mysql> SELECT 18014398509481984*18014398509481984.0;
Activitate 4
mysql> SELECT 18014398509481984*18014398509481984;
/* depasire (numar intreg > 64 bit) */
mysql> SELECT 3/5;
mysql> SELECT 5/(3-3);
NOT
! - Negatie logica. Intoarce 1 daca argumentul este 0, altfel intoarce 0.
Exceptie: NOT NULL intoarce NULL.
OR
|| - SAU logic. Intoarce 1 daca cel putin un argument nu este 0 sau NULL.
AND
&& - SI logic. Intoarce 0 sau NULL daca cel putin un argument este 0 sau
NULL, altfel intoarce 1.
Rulati secventele:
Activitate 5
24
ABD
l
l
l
l
l
l
l
l
l
l
l
Activitate 6
25
ABD
l
l
l
l
Activitate 7
26
ABD
l
l
l
l
l
l
l
l
l
l
l
sus)
ROUND(X) - rotunjire la cel mai apropiat intreg
EXP(X) - exponentiala (e la puterea x)
LOG(X) - logaritm natural din x
LOG10(X) - logaritm in baza 10 din x
POW(X,Y) - x la puterea y
SQRT(X) - radical de ordinul 2 din x
PI() - numarul PI; implicit se afiseaza cu 5 zecimale dar in calcule intervine
cu dubla precizie
COS(X), SIN(X),TAN(X) - cosinus, sinus si tangenta de x
RAND()
RAND(N) - genereaza un numar pseudo-aleator in intervalul [0..1]; prin N se
poate specifica o valoare de initializare calcul
LEAST(X,Y,...) - intoarce cea mai mica valoare din lista valorilor specificate
GREATEST(X,Y,...) - intoarce cea mai mare valoare din lista valorilor
specificate
Rulati secventele:
Activitate 8
l
l
l
l
l
l
l
l
l
l
27
ABD
Activitate 9
Activitate 10
28
ABD
Selectati cu ajutorul comenzii USE baza de date BANCA creata la Tema 2.2.
Creati o tabela Deponent ruland comanda:
Activitate 11
5. Tema 3.1
A) Efectuati cele 11 activitati din acest capitol. Raspunsul va curpinde linii de
forma:
Activitate 1:
hello , "hello" , ""hello"" , hel'lo , 'hello
hello , 'hello' , ''hello'' , hel"lo , "hello
29
ABD
Activitate 2:
2
2
2
... Obs: pentru a rula mai usor secventele se poate face "copy" in fereastra
navigatorului si "paste" in fereastra mySQL.
B) Adaugati la baza de date BANCA tabelele Conturi si Operatii cu urmatoarea
structura:
Conturi
nr_cont char(6) -- de forma 'C23432', cheie primara
nr_buletin char(8) -- cheie externa spre tabela Deponenti, nu poate fi null
tip_cont char(3) -- tipul contului, ex. 'LEI', 'USD' etc.
termen_depozit int(3) -- termen depozit in numar de zile (0 pentru cont curent),
implicit 0
sold int -- suma totala din cont, poate fi negativa daca s-a luat un imprumut
si
Operatii
nr_cont char(6) -- nu poate fi null, cheie externa spre tabela Conturi
suma int -- suma depusa (pozitiva) sau extrasa (negativa)
data timestamp -- data efectuarii operatiei
cheia primara va fi formata din nr_cont+data
Raspunsul va consta intr-o secventa de comenzi ce va creea si verifica crearea
tabelelor.
Pentru a simplifica maniera de scriere a secventelor de cod, acestea vor fi scrise
intr-un fisier text cu extensia .sql editat din NOTEPAD sau orice alt editor text,
putand apoi sa fie rulate foarte simplu din linia de comanda mysql prin comanda:
mysql> SOURCE cale_spre_fisier/nume_fisier.sql;
EX: mysql> SOURCE C:\sql\tema31b.sql;
'2010 confs. dr. ing. Dan Pescaru
30
ABD
La instalarea sistemului este creat implicit un utilizator numit "root" care are toate
drepturile activate. Acest utilizator trebuie folosit, din motive de securitate, doar
pentru administrare. Pentru fiecare utilizator care va interactiona cu serverul
trebuie creat un utilizator.
Foarte important! Desi nu este obligatorie stabilirea unor parole pentru utilizatori
la crearea conturilor acestora, aceasta operatie este de cea mai mare
importanta. In caz contrar securitatea serverului este grav compromisa.
31
ABD
Privilegiu
Context
tabele
tabele
tabele
tabele
tabele
alter
Alter_priv
tabele
create
Create_priv
drop
Drop_priv
grant
Grant_priv
shutdown Shutdown_priv
administrare server
process Process_priv
administrare server
file
File_priv
Semnificatie
permite selectarea (vizualizarea) datelor
permite adaugarea unor noi inregistrari
permite modificarea datelor
permite stergerea inregistrarilor
permite crearea/stergerea indecsilor
permite redenumire sau modificarea
structurii tabelei
permite crearea unei baze de date/tabele
permite stergerea unei baze de date/tabele
permite delegarea privilegiilor catre alt
utilizator
permite oprirea serverului din programul
client
permite vizualizarea/oprirea proceselor in
executie
permite schimbul de date intre tabele si
fisiere
32
ABD
l
l
l
l
l
l
l
33
privilegii - este o lista de privilegii despartite prin virgula. Ele pot fi alese
dintre cele prezentate anterior (SELECT, INSERT, ALTER ...) plus clauza
speciala ALL PRIVILEGES (sau simplu ALL) care specifica toate privilegiile
posibile. Pentru a crea doar utilizatorul fara sa i se dea nici un drept, se va
folosi clauza USAGE.
coloane - o lista de una sau mai multe coloane. Permite stabilirea
ABD
ABD
3. Retragerea privilegiilor
Inversul comenazii GRANT este comanda REVOKE. Ea este utilizata pentru a
retrage drepturile de la un utilizator.
Sintaxa sa este asemanatoare cu cea a comenzii GRANT:
REVOKEprivilegii [coloane]
ONcomponenta
FROMnume_utilizator
Clauzele din aceasta comanda sunt identice cu cele de la comanda GRANT.
Pentru a retrage privilegiul acordat prin clauza WITH GRANT OPTION, se va
utiliza sintaxa:
REVOKE GRANT OPTIONS
ONcomponenta
FROMnume_utilizator
'2010 conf. dr. ing. Dan Pescaru
35
ABD
36
ABD
l
l
37
ABD
l
l
38
ABD
l
l
39
ABD
mysql> DELETE FROM Deponent
WHERE oras='Galati';
mysql> SELECT * FROM Deponent;
# Se vor sterge inregistrarile cu numarul de telefon necompletat:
mysql> DELETE FROM Deponent
WHERE IsNull(telefon);
mysql> SELECT * FROM Deponent;
40
ABD
Cap.7. Interogari
1. Interogarea datelor
1.1. Comanda SELECT
1.2. Utilizarea conditiilor de selectie
1.3. Ordonarea rezultatului
1.4. Folosirea alias-urilor (poreclelor)
1. Interogarea datelor
1.1. Comanda SELECT
Comanda SELECT este cea mai utilizata comanda SQL. Ea permite atat
regasirea si vizualizarea datelor din tabelele bazei de date cat si calcularea unor
expresii care nu au legatura cu datele din tabele.
Sintaxa comenzii SELECT pentru calcularea valorii unor expresii este foarte
simpla si a fost deja folosita in capitolele anterioare:
SELECT expresie;
Ex:
SELECT 3*(5+12);
Utilizarea comenzii SELECT pentru interogarea tabelelor este mai complexa.
Sintaxa de baza a comenzii in acest caz este:
SELECT [SQL_BUFFER_RESULT]
[HIGH_PRIORITY]
[DISTINCT | ALL]
expresie_de_selectie,...
[INTO {OUTFILE | DUMPFILE} 'nume_fisier']
[FROM referinte_tabele
[WHERE conditie_selectie]
[ORDER BY {intreg_pozitiv | nume_col | formula} [ASC | DESC] ,...]
Parametrii din paranteze drepte sunt optionali. Cei din acolade si despartiti prin '|'
sunt obligatorii dar mutual exclusivi (doar unul poate apare).
Ei au urmatoarea semnificatie:
41
ABD
l
42
ABD
43
ABD
44
lista_campuri - specifica acele campuri care vor face parte din rezultat.
Aceste campuri pot fi din oricare tabela specificata in clauza FROM. In
situatia in care un camp din rezultat apare sub acelasi nume in doua sau
mai multe tabele el trebuie prefixat cu tabela din care se extrage. In locul
numelui tabelei se prefera de obicei folosirea unui alias.
lista_tabele - specifica tabelele din care se vor aduna datele. Unele tabele
de aici pot fi doar tabele de legatura intre alte tabele, ele neavand nici un
camp selectat in rezultat. Functie de tipul de operatie JOIN dorit,
lista_tabele poate fi doar o lista de nume despartite prin virgula sau poate
avea o forma mai execta, dupa cum se va preciza in sectiunea urmatoare.
conditii_join - specifica conditiile relationale care leaga tabelele. Ele sunt
de obicei de forma tabela1.cheie_externa=tabela2.cheie_primara AND ....
Daca o legatura lipseste sau este pusa gresit, rezultatul va fi de obiecei un
produs cartezian intre tabele (toate combinatiile posibile intre inregistrari,
fara a tine seama de legaturile relationale).
ABD
l
ABD
SELECT lista_campuri
FROM lista_tabele
WHERE conditii_selectie
GROUP BY {colana | expresie}
HAVING conditie_includere_grup
ORDER BY ...
...
Clauza GROUP BY specifica dupa ce valoare se va face gruparea. In
majoritatea cazurilor expresia de grupare este reprezentata de o singura
coloana. Toate inregistrarile cu aceeasi valoare pentru expresia de grupare vor fi
considerate ca facand parte din acelasi grup.
Daca clauza GROUP BY lipseste, dar in lista_campuri apar informatii de
sumarizare se considera implicit ca toate inregistrarile fac parte din acelasi grup.
Clauza HAVING permite selectarea grupurilor care sunt luate in considerare.
Conditia din HAVING se aplica dupa constituirea grupului, pe cand conditia din
clauza WHERE in timpul selectarii inregistrarilor. In plus, acesta clauza poate
cuprinde doar referinte la campuri si aliasuri de campuri din lista de campuri a
comenzii SELECT sau functii de sumarizare pe grup.
Lista de campuri din comanda SELECT poate include urmatoarele functii de
sumarizare:
l
l
46
ABD
47
ABD
l
http://www.mysql.com/Downloads/Contrib/
l
l
l
l
48
ABD
l
l
l
l
l
l
l
MySQL documentation
l
l
l
l
Pearl5 DBI
49
ABD
l
l
l
l
l
l
l
l
Mai multe informatii despre PHP si utilizarea functiilor PHP-MySQL pot fi gasite
la adresa:
PHP website
ABD
l
l
LOCK TABLES.
2. Se testeaza conditiile de integritate.
3. Se insereaza/modifica datele, daca totul a fost ok la testare.
4. Se deblocheaza tabelele utilizand comanda UNLOCK TABLES.
2.2. Replicarea datelor.
Replicarea datelor se aplica pentru cresterea robustetii si vitezei de acces. Ea
reprezinta un mecanism foarte util in contextul unui server de baze de date.
51
ABD
Cresterea robustetii se face prin utizarea replicarii datelor pe doua siteme - unul
master (principal) si unul backup (de rezerva) - si utilizarea sistemului backup
atunci cand cel principal nu este disponibil.
Pentru cresterea vitezei de acces la date, interogarile care necesita doar citirea
lor din tabele pot fi executate impartit pe master si pe backup. Acest procedeu
este eficient doar daca tabelele respective sunt intensiv accesate pentru citire si
mai putin pentru scriere. Aceasta este insa situatia intalnita pentru majoritatea
tabelelor unei baze de date.
MySQL implementeaza un sistem de replicare intern in arhitectura masterslave. Calculatorul master pastreaza un jurnal cu toate schimbarile efectuate
intr-o baza de date replicata. Calculatorul slave se conecteaza la master,
verifica ce modificari au fost facute si incearca sa le preia. Starea actualizarii
datelor este pastrata de calculatorul slave. In acest fel, chiar daca procesul de
reactualizare este intrerupt prin caderea conexiunii, a calculatorului cu server-ul
master sau a celui cu slave, la reconectare se va continua din punctul ramas,
asigurandu-se corectitudinea procesului.
Pentru a implementa replicarea pe doua servere se vor urma pasii:
l
l
l
l
52
ABD
Contextul in care limbajul PHP poate fi utilizat presupune existenta unui server
de Web. Interpretorul de PHP va actiona ca si modul al acestui server. Schema
generala de lucru este prezentata in figura urmatoare.
53
ABD
Serverul Web incarca pagina din sitemul propriu de fisiere propriu si, constatand
ca este vorba de o pagina PHP o trimite interpretorului PHP.
Interpretorul PHP parcurge pagina si executa instructiunile PHP intalnite.
Instructiunile PHP au ca si scop pricipal acela de a genera cod HTML. De
asemenea, codul HTML din fisierul original este copiat pur si simplu la iesire.
Interpretorul PHP transmite inapoi catre server fisierul transformat prin
interpretarea codul PHP. Acest fisier va contine doar cod HTML (eventual si
JavaScript etc.) dar nu si cod PHP.
Serverul Web raspunde cererii navigatorului transmitandu-i fisierul transformat.
La navigator nu va ajunge nici o instructiune PHP.
Observatie: daca un fisier PHP este incarcat direct in navigator de pe discul
local, prin comanda File/Open, fara a apela un server de Web, documentul
afisat va contine codul PHP neinterpretat. Din aceasta cauza, pentru a crea si
testa documente PHP este nevoie de instalarea lor pe un server de Web.
performanta buna
interfete cu variate sisteme de gestiune a bazelor de date
biblioteci puternice care acopera toate operatiilor Web uzuale
cost scazut
usor de invatat si utilizat
portabil
disponibil ca si cod sursa
Performanta - PHP este foarte eficient. Chiar utilizand un server Web ieftin, pot
fi serviti milioane de clienti pe zi. Mai multe informatii privind eficeinta PHP pot
fi citite la adresa http://www.zend.com.
Interfete cu sisteme de gestiune a bazelor de date - PHP ofera inerfete native
cu cele mai populare sisteme de gestiunea a bazelor de date cum ar fi mySQL,
Oracle, Informix, InterBase, Sybase, FilePro, PostgreSQL etc. De asemenea se
pot realiza conexiuni practic cu orice sistem care ofera un driver de ODBC
(Microsoft Open Database Conectivity standard).
Biblioteci standard - cuprind un numar foarte mare de functii, care ajuta la:
54
ABD
generarea de imagini GIF in mod dinamic, conectarea cu alte servicii din retea,
trimiterea de mesaje e-mail, gestiunea fisierelor cookies sau chiar generarea
automata de documente PDF. Utilizand functiile din biblioteci, toate aceste
operatii se pot implementa in foarte putine linii de cod.
Cost - PHP este gratuit. Ultima varianta este disponibila permanent la adresa:
http://www.php.net .
Invatarea PHP - sintaxa limbajului PHP este bazata in principal pe cea a
limbajelor C si Perl. Din acest motiv, pentru un programator care stie un limbaj
cu sintaxa inrudita cu acestea (ex. Javascript, Java, C++ etc.) va fi foarte usor
de invatat si utilizat.
Portabilitatea - PHP este disponibil pe multe sisteme de operare. Acelasi script
va rula la fel pe o serie de sisteme Unix comerciale gen Solaris sau IRIX,
sisteme UNIX gratuite gen Linux sau FreeBSD sau diverse versiuni de Microsoft
Windows (95, 98, NT, 2000, XP). De asemenea exista foarte multe servere de
Web cu care sistemul PHP poate conlucra.
Disponibilitatea ca si cod sursa - pe langa faptul ca sistemul PHP este gratuit,
este disponibil ca si cod sursa. In acest fel, el poate fi oricand extins sau
modificat daca cineva considera necesar acest lucru.
'2010 conf. dr. ing. Dan Pescaru
55
ABD
56
ABD
In cazul in care nu exista instalat un server Apache se va proceda in felul
urmator:
l
l
l
l
ABD
3.
4.
5.
6.
7.
8.
9.
58
ABD
2.
3.
4.
5.
6.
ftp://ftp.roedu.net/pub/mirrors/ftp.mysql.com/Downloads/MySQL 4.0/mysql-4.0.21-win.zip.
Dezarhivare fisier mysql-4.0.21-win.zip intr-un director temporar (ex
c:\temp).
Se va rula programul setup.exe din directorul de dezarhivare. Directorul
de instalare va fi ales C:\mysql.
Crearea fisierului de configurare se va face prin copierea fisierului my example.cnf din directorul de instalare in radacina discului C sub numele
c:\my.cnf .
Pentru rulare in Winodws 95/98 se va lansa unul din serverele:
mysqld - cu suport de depanare si alocare automata de memorie
mysqld-opt - serverul optimizat pentru sisteme cu procesoare
Pentium
Serverul se va rula din Command Prompt (MS -DOS Prompt) (meniul
Start/Programs/MS-DOS Prompt) tastand: c:\mysql\bin\mysqld sau
c:\mysql\bin\mysqld-opt
Eventualele mesaje de eroare vor fi gasite in fisierul c:\mysql\mysql.err.
ABD
Desi editarea paginilor php se poate face in principiu cu orice editor de text (ex.
Notepad) se recomanda folosirea unui editor specializat, care ofera cel putin
colorarea bazata pe sintaxa si un sistem de ajutor (help) cu informatii despre
functiile php.
Un astfel de editor este Arisesoft Winsyntax v 2.0 si se poate obtine gratuit
de la adresa http://www.winsyntax.com/ .
'2010 conf. dr. ing. Dan Pescaru
60
ABD
2.1.1.
2.1.2.
2.1.3.
2.1.4.
2.1.5.
2.1.6.
stilul "scurt":
<? echo "<H1>Text generat dinamic din PHP</H1?>"; ?>
Avantajul acestui stil este simplitatea. De aici rezulta o visteza mai mare
de scriere a codului.
stilul XML:
<?php echo "<H1>Text generat dinamic din PHP</H1?>"; ?>
Acest stil este compatibil cu documente conforme cu standardul XML
(Extensible Markup Language). Datorita raspandirii in continua crestere a
acestui standard in continuare se va prefera acest stil.
stilul SCRIPT:
<SCRIPT LANGUAGE='php'> echo "<H1>Text generat dinamic din
PHP</H1?>"; </SCRIPT>
Acest stil este destinat celor obisnuiti cu scrierea de cod JavaScript sau
VBScript. Este util daca se foloseste un editor HTML care are probleme cu
alte stiluri de tag -uri.
stilul ASP:
<% echo "<H1>Text generat dinamic din PHP</H1?>"; %>
61
ABD
Acest stil este similar cu cel folosit la ASP (Active Server Pages). Este util
daca se foloseste un editor HTML care genereaza cod ASP.
Texul care apare intre tagul de inceput si cel de incheiere (indiferent de stil) va
fi interpretat ca script PHP. Textul care apare in afara acestor taguri va fi tratat
ca si cod HTML obisnuit.
stilul C: Comentariul se poate intinde pe mai multe linii si este cuprins intre
semnele '/*' si '*/'. El se poate insera chiar si in mijlocul unei expresii dar
nu poate fi imbricat in alt comentariu.
stilul C++: Comentariul se intinde pe o singura linie, de la aparitia
semnului '//' pana la sfarsitul liniei curente.
stilul Shell: Comentariul se intinde pe o singura linie, de la aparitia
semnului '#' pana la sfarsitul liniei curente.
62
ABD
Creati fisierul a2121.php cu urmatorul continut:
Ex. 1
<HTML>
<HEAD>
<TITLE>Activitate 1.</TITLE>
</HEAD>
<BODY>
<H2>Exemplu de generare dinamica de cod.</H1><P>
Linia urmatoare este generata de PHP:<P>
<?php
echo "Data curenta pe server: ";
echo date ("H:i, jS F"); // se obtine data si ora curenta cu ajutorul
functiei date()
echo "<BR>";
?>
</BODY>
</HTML>
Incarcati fisirul direct in navigator (prin File/Open) si apoi copiati
fisierul in directorul htdocs al serverului de Web si incarcati
adresa http://localhost/a2121.php
In plus, PHP suporta si tipurile pdfdoc respectiv pdfinfo pentru a asigura suport
pentru PDF (standardul Portable Document Format).
PHP este un limbaj slab tipizat. In limbajele puternic tipizate, o variabila poate
retine un singur tip de date pe toata durata sa de viata, tip asignat la
declararea acelei variabile. In PHP varibilele nu trebuie declarate explicit (ele
sunt considerate ca fiind declarate implicit la prima lor utilizare in cod), iar tipul
de date asignat este determinat de valoarea retinuta in acel moment.
Urmatoarele linii de cod sunt corecte in PHP (numele variabilelor PHP sunt
prefixate de semnul $):
$var1 = 1;
$var1 = "sirul 1";
Tipul datelor extrase din variabile poate fi schimbat fortat (casting sau
conversie de tip) in expresiile unde acestea intervin. Acest lucru se face prin
63
ABD
precizarea noului tip intre paranteze rotunde in fata variabilei respective:
$var1 = 1;
$var2 = (double)$var1 + 3.52;
Conversia de tip nu afecteaza tipul real al varibilei.
l
l
Identificatorii pot fi de orice lungime si pot fi formati din litere, cifre, liniuta
de subliniere sau semnul dolar.
Identificatorii nu pot incepe cu o cifra.
Identificatorii sunt de tip "case sensitive" (tin cont de litere mici-mari).
Spre exemplu, $numepers este diferit de $numePers. Singurii identificatori
care nu respecta aceasta regula sunt cei care denota nume de functii PHP
predefinite.
ABD
cu semnul $. Ele permit memorarea valorilor de diverse tipuri. Tipul unei
variabile PHP poate fi modifcat in momentul cand i se asigneaza o valoare.
Declararea variabilelor utilizator nu trebuie facuta explicit. O variabila se
considera declarata implicit prima data cand este folosita.
Pentru a asigna o valoare unei variabile se va folosi operatorul = sub forma
$variabila = expresie. Daca $variabila nu exista ea va fi creata in prealabil apoi i
se va asigna valoarea expresiei.
Varibilele referinta permit schimbarea numelui unei variabile in mod dinamic.
Acest lucru se face prin utilizarea valorii unei varibile pe post de nume de
variabila. Indirectarea se realizeaza prin utilizarea marcajului dolar '$' in fata
numelui variabilei referinta, ca si in exemplul urmator:
$var1 = 5;
$var2 = "var1";
echo "Valoarea din var1 este ";
echo $var1;
echo " sau ";
echo $$var2;
In acest exemplu notatia $$var2 a fost folosita pentru a desemna valoarea
retinuta de varibila $var1.
Prin domeniul de valabilitate a unei variabile se intelege locurile in care o
variabila poate fi folosita (este vizibila) dupa ce a fost creata. Domeniile definite
de PHP sunt urmatoarele:
l
ABD
prezentat, paginile tinta ale formularelor vor fi fisiere PHP, paginile cuprinzand
formularele putand fi fisiere PHP sau HTML.
Mai multe informatii despre formulare HTML se pot obtine la adresa
http://www.w3.org/MarkUp/.
In PHP datele dintr-un formular HTML pot fi accesate prin doua metode.
Prima metoda, mai simpla dar mai inceata si mai nesigura, consta in folosirea
varibilelor inregistrate global. In acest fel numele campurilor dintr-un formular
HTML devin automat varibile PHP, cu valori setate corespunzator, in pagina tinta
a formularului. Transmiterea se face asemanator cu transmiterea parametrilor
spre functii. Pentru a putea folosi aceasta metoda trebuie ca fisierul de
configurare php.ini sa aiba setarea register_globals pe valoarea "On".
A doua metoda presupune obtinerea valorilor din doua tablouri create automat
si denumite $_POST, respectiv $_GET corespunzator metodei de trimitere din
formular spre server (post sau get). Indicele de acces in tablou va fi chiar
numele campului dorit din formular.
In scripturile profesionale, unde viteza si securitatea sunt determinante, a doua
metoda este de preferat.
ABD
Creati fisierul a2162.php cu urmatorul continut:
Ex. 2
<HTML>
<HEAD>
<TITLE>Activitate 2 (procesare)</TITLE>
</HEAD>
<BODY>
<H1>Prelucrare date din formularul a261.html</H1>
<HR>
<?php
$numePers = $_POST["numePers"];
$prenumePers = $_POST["prenumePers"];
$transport = $_POST["transport"];
echo "Nume persoana: ".$numePers."<BR>";
echo "Prenume persoana: " .$prenumePers ."<BR>";
echo "Mijloc de transport preferat: ".$transport ."<BR>";
$nume =$numePers." " .$prenumePers;
echo $nume." prefera sa calatoreasca cu
".$transport ."."."<BR>";
?>
<HR>
</BODY>
</HTML>
Copiati fisierele in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a2161.html. Completati
formularul si apasati apoi butonul Submit.
67
ABD
2.2.1. Operatori
2.2.1.1. Operatori aritmetici
2.2.1.2. Operatori pe siruri de caractere
2.2.1.3. Operatori de asignare
2.2.1.4. Operatori de referire
2.2.1.5. Operatori de comparare
2.2.1.6. Operatori logici
2.2.1.7. Operatori pe biti
2.2.1.8. Operatori aditionali
2.2.2. Expresii
Denumire
adunare
scadere
inmultire
impartire
modulo
incrementare - post
incrementare - pre
decrementare - post
decrementare - pre
Exemplu
$a + $b
$a - $b
$a * $b
$a / $b
$a % $b
$a++
++$a
$a---$a
68
ABD
rezultat cresterea/descresterea cu o unitate a varibilei operand asupra careia se
aplica. Operatorii post se aplica dupa ce valoarea este evaluata in expresia din
care face parte iar operatorii pre se aplica inainte de evaluarea expresiei. Ex:
$a = 5;
$b = $a++; // b = 5, a = 6
$c = ++$a; // c = 7, a = 7
$d = 4 + --$a; // d = 10, a = 6
$e = 4 + --$c; // e = 11, c = 6
Daca operatorii aritmetici se aplica asupra unor valori de tip string, PHP va
incerca conversia acestora in numere. Daca conversia nu reuseste, sirurile sunt
convertite la valoarea 0.
Creati fisierul a2211.php cu urmatorul continut:
Ex. 1
<HTML>
<HEAD>
<TITLE>Activitate 2.2.1.1.</TITLE>
</HEAD>
<BODY>
<H2>Operatori aritmetici.</H1><P>
<?php
$a = 3;
$b = 11;
$c = 4.7;
echo "a = "; echo $a; echo "<BR>";
echo " b = "; echo $b; echo "<BR>";
echo " c = "; echo $c; echo "<BR>";
echo "a - b = "; echo $a - $b; echo "<BR>";
echo "a * c = "; echo $a * $c; echo "<BR>";
echo "b % a = "; echo $b % $a; echo "<BR>";
echo "b % c = "; echo $b % $c; echo "<BR>";
echo "b + --a= "; echo $b + --$a; echo "<BR>";
echo "a / 0 = "; echo $a / 0; echo "<BR>";
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a2211.php
ABD
$s3 = $s1."-".$s2; // s3 = "Sirul 1-Sirul 2"
Utilizare
$a += $b
$a -= $b
$a *= $b
$a /= $b
$a %= $b
$s1 .= $s2
Echivalent cu
$a = $a + $b
$a = $a - $b
$a = $a * $b
$a = $a / $b
$a = $a % $b
$s1 = $s1 . $s2
ABD
Operatorii de comparare sunt operatori binari care au ca si scop compararea
valorilor operanzilor. Rezultatul acestor operatori este unul logic, avand
valoarea true (adevarat) sau flase (fals).
Acestia sunt:
Operator
==
===
!=
<>
<
>
<=
>=
Denumire
egalitate
test de identitate
inegalitate
inegalitate
mai mic
mai mare
mai mic egal
mai mare egal
Exemplu
$a == $b
$a === $b
$a != $b
$a <> $b
$a < $b
$a > $b
$a <= $b
$a >= $b
Denumire
negare
si logic
si logic
||
sau logic
or
sau logic
xor
sau
exclusiv
Rezultat
!$a neaga valoarea logica a lui $a
$a && $b intoarce adevarat doar daca ambele valori $a si $b sunt adevarate
$a and $b intoarce adevarat doar daca ambele valori $a si $b sunt adevarate
$a || $b intoarce adevarat daca cel putin una dintre valorile lui $a sau $b
este adevarata
$a or $b intoarce adevarat daca cel putin una dintre valorile lui $a sau $b
este adevarata
$a xor $b intoarce adevarat daca $a si $b au valori logice diferite
71
Rezultat
ABD
~
&
|
^
<<
>>
negare pe biti
si pe biti
sau pe biti
sau exclusiv pe
biti
deplasare stanga
deplasare dreapta
72
ABD
Asociativitate Operator
stanga
,
stanga
or
stanga
xor
stanga
and
stanga
= += -= *= /= .= %=
stanga
?:
stanga
||
stanga
&&
stanga
|
stanga
^
stanga
&
== != ===
< > <= >=
stanga
<< >>
stanga
+-.
stanga
*/%
dreapta
! ~ ++ -- @
dreapta
[]
new
()
O atentie deosebita trebuie acordata sirurilor de caractere intre ghilimele " " . La
evaluarea expresiei in care acestea apar, toate numele de variabile care apar in
interiorul lor sunt inlocuite cu valorile corespunzatoare. Exemplu:
$nume = "Vasile";
$sir1 = "Domnul $nume are masina rosie!";
$sir2 = 'Domnul $nume are masina rosie!';
echo $sir1; // afiseaza Domnul Vasile are masina rosie!
echo $sir2; // afiseaza Domnul $nume are masina rosie!
73
ABD
Creati fisierul a2221.php cu urmatorul continut:
Ex. 2
<HTML>
<HEAD>
<TITLE>Activitate 2.2.2.1.</TITLE>
</HEAD>
<BODY>
<H2>Operatori si expresii.</H1><P>
<?php
$nume = "Ionescu";
$prenume = "Vasile";
$varsta = 38;
$salar = 1500;
$prop1 = "Domnul $prenume $nume are $varsta ani."."<BR>";
echo $prop1;
$prop2 = "Domnul ".$nume." are salar ".
(($salar<1000)?"mic":"mare")."!<BR>";
echo $prop2;
$salarNou = & $salar; // salarNou indica spre salar
$procentMarire = 26; // procentul cu care se mareste salarul
$salarNou += $salarNou*($procentMarire / 100);
$prop3 = " Salarul sau dupa marire este de $salar $."; // salar si
salar nou indica spre aceiasi valoare
echo $prop3;
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a2221.php
74
ABD
ABD
if ($nota < 5)
{
echo 'Examenul trebuie repetat!';
$bursa = 0;
}
In multe cazuri, pentru conditie neadevarata se doreste executia altei
instructiuni sau a unu bloc de instructiuni. In acest caz se va folosi clauza
optionala else. Exemplu:
if ($nota < 5)
{
echo 'Examenul trebuie repetat!';
$bursa = 0;
}
else
{
echo 'Felicitari pentru trecerea examenului!';
$bursa = 1000000;
}
In unele situatii, la luarea unei decizii exista mai multe optiuni. In acest caz ar
trebui testate mai multe conditii. Pentru aceasta, limbajul PHP pune la dispozitia
programatorilor clauza elseif. In acest caz sintaxa instructiunii este:
if (expr1)
instructiune1
elseif (expr2)
instructiune2
...
elseif (expr3)
instructiune
Exemplu:
if ($nota < 5)
{
echo 'Insuficient';
$bursa = 0;
}
elseif ($nota<7)
{
echo 'Suficient';
$bursa = 500000;
}
elseif ($nota<9)
{
echo 'Bine';
$bursa = 1000000;
76
ABD
}
else
{
}
echo 'Bine';
$bursa = 1500000;
ABD
case 10:
echo ' bursa este 1500000.';
break;
defaut:
echo 'nota nu este corecta!';
ABD
Ex. 1
instructiune
while (expr);
Expresia expr este o expresie (conditie) logica ce se evalueaza dupa fiecare
repetitie. Daca, dupa executarea instructiunii conditia este adevarata se va
relua secventa de la inceput. In cazul in care conditia devine falsa, repetitia se
va incheia si se va trece la intructiunea de dupa do-while.
Exemplu:
echo "Se genereaza un sir de numere aleatoare in intervalul 0-100.<BR>";
echo "Generarea se opereste la primului numar mai mare de 90 sau cand s-au
depasit 20 de numere.<BR>";
$i = 1;
do
{
$n = rand(0,100);
echo 'Numarul '.$i++." = ".$n."<BR>";
} while ($n<=90 and $i<21);
In cazul buclei do-while, instructiunea din bucla se va executa cel putin o data
79
ABD
chiar si in cazul in care conditia nu este adevarata de la inceput.
80
ABD
Sintaxa pentru crearea unui tablou indexat numeric este:
$tablou = array (el0, el1, ... el_n);
Exemplu:
$culori= array ("alb", "albastru", "verde", "rosu", "galben");
Accesul la elementele tabloului se face prin indecsi numerici (cu semnificatia de
numere de ordine in tablou). Spre exemplu $culori[0] are valoarea "alb", $culori
[4] are valoarea "galben" etc.
In PHP dimensiunea unui tablou este variabila. Pentru a adauga un nou element
se va atribui pur si simplu variabilei cu urmatorul indice o anumita valoare. Spre
exemplu $culori[5]="negru" va adauga un nou element ("negru") la sfarsitul
tabloului $culori.
Numarul curent de elemente ale unui tablou se poate afla in orice moment cu
ajutorul functiei count($tablou).
Tablourile asociative sunt tablouri in care valorilor continute le sunt asociate
chei prin care acestea pot fi regasite. Sintaxa pentru crearea unui astfel de
tablou este:
$tablou = array( "cheie1" => el1, "cheie2" => el2, ... "cheie_n" => el_n);
Exemplu:
$pret = array ("paine alba" => 7000, "ou" => 3000, "zahar" => 24000);
Accesul la un element se face prin cheia asociata. Spre exemplu $pret["paine
alba"] are valoarea 7000. Si in acest caz tabloul poate si extins dinamic prin
adaugarea unui nou element a carei cheie nu exista in tablou. Spre exemplu
$pret["miere 500g"] = 30000 va adauga elementul 30000 cu cheia "miere
500g" la tabloul $pret, acesta avand acum patru elemente.
Ambele tipuri de tablouri retin intern o referinta (pointer) catre elementul
curent de prelucrat. Acest lucru permite scrierea secventelor pentru
parcurgerea si prelucrarea elementelor lor.
Instructiunea foreach este asemanatoare cu instructiunea for dar este
destinata exclusiv parcurgerii de tablouri, in special a celor asociative. Sintaxa
acestei instructiuni are doua forme alternative:
foreach (tablou as valoare_element_curent)
instructiune
foreach (tablou as cheie => valoare_element_curent)
instructiune
Prima forma permite extragerea tuturor valorilor din tablou si prelucrarea lor
81
ABD
individual, pe cand cea de a doua forma permite si extargerea si prelucrarea
cheilor asociate.
Creati fisierul a3124.php pentru a genera o tabela de conversie
valutara.
Ex. 2
82
<HTML>
<HEAD>
<TITLE>Activitate 3.1.2.4.</TITLE>
</HEAD>
<BODY>
<H2>Parcurgerea tablourilor.</H1>
<P>
<?php
$culori= array ("alb", "albastru", "verde", "rosu", "galben");
$pret = array ("paine alba" => 7000, "ou" => 3000, "zahar" =>
24000);
echo "<P>Tablou indexat numeric, extragere valori.<BR>";
echo "<UL>";
foreach ($culori as $culoare)
echo "<LI>".$culoare."</LI>";
echo "</UL>";
echo "<P>Tablou indexat numeric, extragere valori si
indecsi.<BR>";
echo "<TABLE border=1>";
foreach ($culori as $indice => $culoare)
{
echo "<TR>"; // se creaza o noua linie in tabel
echo "<TD>"; // se creaza coloana pentru valoarea indexului
echo $indice; // se completeaza valoarea indexului
echo "</TD> <TD>"; // se creaza coloana pentru culori
echo $culoare; // se completeaza culoarea
echo "</TD> </TR>"; // se inchide linia curenta
}
echo "</TABLE>";
echo "<HR>";
echo "<P>Tablou asociativ, extragere valori.<BR>";
echo "<UL>";
foreach ($pret as $pret_produs)
echo "<LI>".$pret_produs."</LI>";
echo "</UL>";
echo "<P>Tablou asociativ, extragere valori si chei.<BR>";
echo "<TABLE border=1>";
foreach ($pret as $produs => $pret_produs)
{
echo "<TR>"; // se creaza o noua linie in tabel
echo "<TD>"; // se creaza coloana pentru valoarea cheii
(produsul)
echo $produs; // se completeaza valoarea cheii
ABD
echo "</TD> <TD>"; // se creaza coloana pentru pret
echo $pret_produs; // se completeaza pretul
echo "</TD> </TR>"; // se inchide linia curenta
}
echo "</TABLE>";
?>
</HR>
</BODY>
</HTML>
83
ABD
while sau do..while . Exemplu - se considera exemplul anterior, dar daca se
genereaza numarul 0 nu se va executa impartirea si se va trece la generarea
urmatorului numar:
for ($i=1; $i <= 20; $i++)
{
$a = rand(0,50);
if ($a == 0)
{
echo "S-a generat 0.<BR> ";
continue;
}
echo "Pasul $i: 1000 / $a = ".(1000/$a)."<BR>";
}
echo "Generare terminata !";
Instructiunea return permite terminarea fortata a functiei sau programului
curent. Ea poate fi folosita in instructiunile for, foreach, while sau do..while
unde, prin terminarea scriptului, termina in mod evident si bucla curenta. Daca
se doreste generarea unui mesaj in pagina inainte de incheierea scriptului, in
loc de return se pot folosi functiile exit(mesaj) sau die(mesaj) - die fiind un alias
al functiei exit. Exemplu - in exemplul anterior, la generarea lui 0 se termina
fortat pagina:
for ($i=1; $i <= 20; $i++)
{
$a = rand(0,50);
if ($a == 0)
{
echo "Eroare: S-a generat 0.";
return;
}
/* alternativ se poate folosi secventa
if ($a == 0)
die("Eroare: S-a generat 0.");
*/
echo "Pasul $i: 1000 / $a = ".(1000/$a)."<BR>";
}
echo "Generare terminata !";
'2010 conf. dr. ing. Dan Pescaru
84
ABD
3.2.1. Functii
3.2.1.1. Functii de biblioteca
3.2.1.2. Functii utilizator
3.2.1.3. Transmiterea parametrilor
3.2.1.4. Functii recursive
3.2.2. Reutilizarea codului
3.2.2.1. Instructiunea require
3.2.2.2. Instructiunea include
3.2.3. Cotrolul sesiunilor
3.2.4. Utilizare formulare si sesiuni pentru controlul utilizatorilor
ABD
In cele mai multe dintre cazuri, functiile au ca si scop prelucrarea unor date de
intrare transmise sub forma unor paramerii (variabile) de apel. Acesti
parametrii se specifica intr-o lista de expresii despartite prin virgula in
momentul apelului:
nume_functie( parametrul1, parametrul2, ... parametrul_n);
Un exemplu in acest sens este functia asort(tablou ). Aceasta functie primeste
ca si argument un tablou asociativ unidimensional si il ordoneaza dupa valoarea
elementelor sale.
$masini = array ( "Dacia" => "Supernova", "Bmw" => "316i", "Renault" =>
"Clio", "Audi" => "A2");
asort($masini);
foreach($masini as $marca => $masina)
echo $masina." (".$marca.")<BR>";
Unele functii au ca si scop calcularea unei valori. Aceasta valoare este apoi
returnata prin numele functiei. Apelul acestor functii poate fi facut in interiorul
expresiilor.
$var1 = functie_oarecare( lista_paramertri1 );
$var2 = 30 * ( 2 + functie_numerica( lista_parametrii2 ) );
$var3 = "text:".functie_caracter ( lista_parametrii3);
Un astfel de exemplu este functia number_format(numar) care are ca scop
formatarea un numar cu virgule pe pozitia miilor, milioanelor etc.
$sir1 = "Salarul net: ".number_format($salar);
ABD
plus, un nume de functie poate contine numai litere, cifre sau liniuta de
subliniere; numele nu poate incepe cu o cifra si nu poate fi identic cu cel al unei
functii de biblioteca.
ABD
parametrului transmis, copie ce va contine valoarea de apel. Orice modificare
asupra parametrului efectuata in interiorul functiei nu va fi vizibila in exteriorul
acesteia. Exemplul urmator scoate in evidenta tocmai acest lucru:
function schimba( $a, $b )
{
echo "Apel schimba cu a=$a si b=$b. <BR>";
$c = $b;
$b = $a;
$a = $c;
}
$x = 1;
$y = 3;
echo "Inainte de apel: x=$x si y = $y. <BR>";
schimba( $x, $y);
echo "Dupa apel: x=$x si y = $y. <BR>";
Pentru a propaga modificarile parametrilor realizate in interiorul functiei trebuie
schimbata metoda de transmitere a lor. Transmiterea parametrilor ptin referinta
presupune crearea unei referinte (alias) a parametrului transmis. In felul acesta
nu se mai realizeaza o copie a parametrului ci, dinpotriva, la parametrii
transmisi prin referinta numele parametrului din functie (numit parametru
formal) va referi aceiasi zona de memorie ca si cea a parametrului transmis.
Transmiterea parametrilor prin referinta se specifica prin plasarea semnului '&'
in inaintea acestor parametrii, la declararea functie. La apel, parametrilor
transmisi prin referinta le pot corespunde doar nume de variabile nu si expresii
sau constante.
function schimba( &$a, &$b )
{
echo "Apel schimba cu a=$a si b=$b. <BR>";
$c = $b;
$b = $a;
$a = $c;
}
$x = 1;
$y = 3;
echo "Inainte de apel: x=$x si y = $y. <BR>";
schimba( $x, $y);
echo "Dupa apel: x=$x si y = $y. <BR>";
ABD
sunt calculul seriilor matematice recursive sau navigarea prin structuri de date
dinamice gen liste inlantuite sau arbori.
La aplicatiile Web utilitatea functiilor recursive este mai restransa. Totusi, o
serie de algoritmi repetitivi de prelucrare a textelor sau de prelucrarea a
tablourilor asociative pot profita de aceasta tehnica.
In general insa trebuie retinut ca un algoritm implementat printr-o functie
recursiva este de obicei mai incet si consuma mai multa memorie decat acelasi
algoritm implementat iterativ.
In exemplul urmator se prezinta o functie recursiva pentru afisarea inversa a
unui sir de caractere:
function afis_inversat($sir)
{
if (strlen($sir)>0)
afis_inversat(substr($sir, 1)); // apelul recursiv al functiei
echo substr($sir, 0, 1);
}
$mesaj = "Iarna este ger!";
afis_inversat($mesaj);
La scrierea unor functii recursive trebuie acordata o mare atentie iesirii din
recursivitate. Apelul recursiv din interiorul functiei va fi executat intotdeauna
conditionat.
ABD
cu numarul de erori existente intr-un produs. Aceasta se poate obtine in general
printr-o faza de testare corect dimensionata. Este evident faptul ca o portiune
de cod "matura", care a fost deja testata inclusiv de catre beneficiari, este de
preferat unei secvente noi, care poate include o serie de erori dificil de detectat.
Consistenta. La dezvoltarea unei linii de produse software un aspect important
il constituie consistenta interfetei cu utilizatorul si a comportamentului
aplicatiilor respective. Reutilizarea codului existent duce automat la asigurarea
consitentei cu celelalte produse care folosesc acelasi cod.
Limbajul PHP pune la dispozitia programatorilor doua instructiuni foarte utile
raportat la reutilizarea codului: require si include.
ABD
?>
Se poate observa necesitatea introducerii codului intre taguri php. In absenta
acestor taguri, codul este interpretat ca si text (codificat HTML) si afisat ca
atare la iesire.
Includerea codului prin require poate fi folosita si la scrierea unor biblioteci de
functii care sa fie inclusa in alte fisire sau poate fi folosita la crearea unui aspect
standardizat pentru un set de pagini (o macheta - "page template").
91
ABD
O alta deosebire importanta consta din faptul ca instructiunea include poate
returna o valoare in programul apelant, valoare care poate fi testata sau folosita
de acesta.
// fisierul generezPI.php
<?php
echo "fisierul genereaza numarul PI<BR>";
return 3.14;
?>
// fisier folosestePI.php
<?php
echo "fisierul care foloseste numarul PI<BR>";
$PI = include( "genereazaPI.php" );
echo "<B>PI</B> = ".$PI;
?>
92
ABD
paginii
stergerea variabilelor sesiune si distrugerea sesiunii
Inainte de a utiliza o sesiune aceasta trebuie creata. Cel mai simplu mod de a
porni o sesiune este acela de a apela functia session_start(). Apelul acestei
functii creeaza automat un numar de sesiune si permite apoi utilizarea
variabilelor de sesiune. Aceasta functie trebuie apelata inainte de antetul
"<HTML>". O alta metoda, mai putin recomandata, este metoda creari implicite
a unei sesiuni in momentul in care se inregistreaza fortat o variabila de sesiune.
Functia session_start va fi apelata la inceputul tuturor paginilor care compun
sesiunea curenta.
Pentru a folosi valori transmise intre pagini diferite se vor folosi variabile
sesiune. Variabilele sesiune se inregistraza ca atare prin apelul functiei
session_register (nume_variabila). De exemplu:
$varSesiune1 = 10;
session_register ( "varSesiune1");
Trebuie remarcat ca numele variabilei se transmite functiei ca si un sir de
caractere, fara a include si semnul $. Variabila va ramane vizibila pana cand
este stearsa sau pana cand sesiunea curenta se incheie. Daca se doreste, se pot
inregistra mai multe variabile printr-un singur apel de session_register prin
sintaxa:
session_register ( "v1", "v2" ...);
Pentru a utiliza variabilele sesiune in alte pagini din aceeasi sesiune exista doua
metode, asemanator cu accesul la datele unui formular. Daca optiunea
register_globals din php.ini este setata pe On, in toate paginile sesiunii
variabila va fi accesibila direct prin nume. Daca optiunea este Off se poate apela
variabila prin intermediul tabloului asociativ $HTTP_SESSION_VARS. De
exemplu:
$n = 4 * $HTTP_SESSION_VARS["varSesiune1"];
Pentru a testa intr-o pagina daca o variabila a fost sau nu inregitrata in
sesiunea curenta se va folosi functia session_is_registered("numeVariabila").
Aceasta functie intoarce o valoare logica care poate fi ulterior testata.
Daca se doreste la un moment dat stergerea unei variabile sesiune se poate
apela la functia session_unregister(numeVariabila).
Pentru a incheia sesiunea cureta si a sterge toate variabilele sesiune asociate se
va apela functia session_destroy(). Aceasta functie nu primeste nici un
parametru si va distruge sesiunea curenta impreuna cu toate informatiile
asociate.
Observatie! Pentru a functiona corect mecanismul de control al
93
ABD
sesiunii trebuie ca in fisierul php.ini sa existe setarile:
session.save_path = c:/temp
;setare valabina pentru Windows (pt. Unix: session.save_path
= /tmp)
session.cache_limiter = private
Ex. 1
94
ABD
</HTML>
Creati fisierul a3233.php pentru pagina parsonalizata si sfarsitul
sesiunii.
<?php
session_start();
?>
<HTML>
< HEAD><TITLE>Activitate 3.2.3.3.</TITLE></HEAD>
<BODY>
<?php
echo "Aceasta este pagina personalizata pentru uilizatorul
$utilizator!<BR>";
session_destroy();
?>
</BODY>
</HTML>
Copiati fisierele in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a3231.html
95
ABD
Cap. 16. Fisiere
4.1.1. Functii de biblioteca
4.1.1.1. Functii de prelucrare tablouri
4.1.1.2. Functii de prelucrare date calendaristice
4.1.1.3. Functii matematice
4.1.1.4. Functii de prelucrare siruri de caractere
4.1.2. Utilizare fisiere
4.1.2.1. Deschiderea si inchiderea unui fisier
4.1.2.2. Scrierea intr-un fisier
4.1.2.3. Citirea dintr-un fisier
4.1.2.4. Functii speciale pentru fisiere
4.1.3. Tema 4.a
96
ABD
Functia array_key_exists testeaza daca o anumita cheie exista intr-un tablou
asociativ.
l
Functia print_r este folosita in special pentru depanare, pentru a afisa continutul
unei variabile intr-un mod usor de citit si inteles pentru om. In cazul in care
varibila este tablou, se va afisa in clar asocirea index=>valoare sau
97
ABD
cheie=>valoare. Daca se doresc parcurgeri multiple trebuie apelata functia
reset(tablou ) dupa fiecare apel al functiei print_r.
Creati fisierul a4111.php referitor la functii de prelucrare tablouri.
<HTML>
<HEAD><TITLE>Activitate 4.1.1.1.</TITLE></HEAD>
<BODY>
Activitate
1
<?php
$preturiProduse = array( " paine" => 6000,
"ou" => 3200,
" mere" =>23000,
"biscuiti" => 16000 );
echo "Tabloul original:<BR>";
print_r($preturiProduse);
asort($preturiProduse);
echo "<P><HR>Tabloul sortat prin <B>sort()</B>:<BR>";
print_r($preturiProduse);
krsort($preturiProduse);
echo "<P><HR>Tabloul sortat prin <B>krsort()</B>:<BR>";
print_r($preturiProduse);
$preturiNoi = array ( "ou" => 3500,
"lapte" => 11000) ;
$preturiProduse = array_merge($preturiProduse, $preturiNoi);
echo "<P><HR>Se adauga tabloul de preturi noi:<BR>";
print_r($preturiNoi);
echo "<BR>Prin utilizarea <B>array_merge</B> a
rezultat:<BR>";
print_r($preturiProduse);
echo "<P><HR>Noul tablou are ".count($preturiProduse)."
elemente. <BR>";
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a4111.php
98
ABD
Functia getdate creaza un tablou asociativ continand informatii despre data
specificata de parametrul optional UNIX timestamp sau, despre data curenta a
serverului daca parametrul lipseste. Tabloul asociativ va avea urmatoarele chei:
"seconds", "minutes", "hours", "mday" (ziua lunii in intervalul 1..31),
"wday" (ziua din saptamana: 0 - duminica .. 6 - sambata), "mon" (luna in
format 1 .. 12), "year" (anul pe 4 cifre), ydey (ziua din an: 1 .. 366),
"weekday" (ziua saptamanii, text in engleza), "month" (luna, text in engleza).
l
int time ( );
Functia date transforma o data din forma UNIX timestamp sau data curenta
(daca parametrul lipseste) intr-un sir de caractere conform machetei format.
Macheta este un sir de caractere care poate cuprinde urmatoarele caractere:
Caractere Semnificatie
a
'am' sau 'pm'
Caractere Semnificatie
A
'AM' sau 'PM'
ziua in saptamana pe 3 caractere
D
'Mon' .. 'Sun'
minute 00..59
m
n
luna 01..12
luna 1..12
sufixul in engleza pentru ziua
lunii
'st', 'nd', 'rd', sau 'th'
ziua saptamanii 0(duminica)..6
(sambata)
anul pe doua cifre
M
s
S
w
y
99
anul pe 4 cifre
ABD
Creati fisierul a4112.php referitor la functii de prelucrare date
calendaristice.
<HTML>
<HEAD><TITLE>Activitate 4.1.1.2.</TITLE></HEAD>
<BODY>
Activitate
2
<?php
$acum = time();
echo "<P>Data curenta (Unix timestamp): ".$acum."<BR>";
echo "<P>Data curenta (<b>date('\R\u\l\a\\t \a\s\\t\a\z\i, d F Y
\l\a \o\\r\a h:i:s A.'): ".date('\R\u\l\a\t \a\s\t\a\z\i, d F Y \l\a
\o\r\a h:i:s A.', $acum)." <BR>";
echo "<P>Tabloul obtinut prin apelul getdate()<BR>";
$dataCrt = getdate();
print_r($dataCrt);
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a4112.php
Valoare
3.14159265358979323846
2.7182818284590452354
1.4426950408889634074
0.69314718055994530942
1.41421356237309504880
0.57721566490153286061
Semnificatie
numarul PI
numarul e
log in baza 2 din e
ln(2)
Radical din 2
contanta lui Euler
ABD
l
Functia ceil rotunjeste in sus valoarea parametrului. Desi rezultatul este intreg,
el este retunat tot sub forma de float.
l
Functia floor rotunjeste in jos valoarea parametrului. Desi rezultatul este intreg,
el este retunat tot sub forma de float.
l
Functiile cos, sin si tan calculeaza valoarea coresponedenta din unghiul dat in
radiani.
l
l
Functiile max si min calculeaza valoarea maxima (minima) din sirul de valori
transmise ca si parametru. Functiile pot primi oricati parametrii. Daca primul
parametru este numeric, se va calcula valoarea maxima (minima) dintre valorile
continute.
l
101
ABD
Functia mt_rand genereaza un numar aleator. Valoarea generata va fi in
intervalul [0..mt_getrandmax()] daca min si max lipsesc, in intervalul [0..max]
daca min lipseste, respectiv in intervalul [min..max] daca ambii parametrii sunt
prezenti.
l
Activitate
3
<?php
for($i=0; $i<6; $i++)
$noteExamene[$i] = mt_rand( 4, 10 );
echo "<P>Sirul de note obtinute in sesiune<BR>";
print_r( $noteExamene );
echo "<P> Nota maxima obtinuta in sesiune:".max
($noteExamene)." <BR>";
echo "<P>Suma notelor obtinute: ";
for ($suma=$i=0; $i<count( $noteExamene); $i++)
$suma += $noteExamene[$i];
echo $suma."<BR>";
echo "<P>Media notelor obtinute: ".($suma / count
($noteExamene))."<BR>";
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a4113.php
Functia chr transforma un numar intre 0 si 255 intr-un sir continand caracterul
corespunzator codului ASCII al acestuia.
l
102
ABD
caracter din sirul transmis ca si parametru.
l
Functiile ltrim, rtrim, trim elimina spatiile albe de la inceputul, sfarsitul respectiv
din ambele capete ale sirului transmis ca si parametru. Sunt considerate ca si
spatii albe caracterele spatiu, tab, linie noua si NULL.
l
l
%d
%f
%s
l
l
Caracter Semnificatie
argumentul este considerat ca intreg
%c
si transformat in caracterul ASCII
corespunzatoare valorii sale
%u
intreg fara semn reprezentat binar
%o
intreg reprezentat octal
%X
intreg reprezentat hexazecimal
103
ABD
l
Functia substr extrage subsirul care incepe pe pozitia start si are lungima
lungime din sirul transmis ca si parametru. Daca parametrul lungime lipseste,
lungimea se considera pana la sfarsitul sirului original.
l
Functiile ucfirst si ucwords transforma prima litera din primul cuvant, respectiv
prima litera din toate cuvintele din sir, in litera mare.
l
l
Functiile strtolower si strtoupper transforma toate literele din sir in litere mici,
respectiv litere mari.
Activitate
4
104
<?php
$sir = "alin dinu george ion laurentiu ovidiu serban";
$adresa = "cineva@servermail.ro";
$sirCorect = ucwords ( $sir );
$tNume = explode ( " ", $sirCorect );
echo "<P> Sirul de nume: ".$sir."<BR>";
echo "<P> Sirul corectat prin ucword: ".$sirCorect."<BR>";
echo "<P> Tabloul rezultat prin expode:<BR>";
print_r ( $tNume );
$sirNou = implode ( ",", $tNume );
printf ( "<P> printf: Sirul '%s' are lungimea %d.<BR>", $sirNou,
strlen( $sirNou ));
$poz = strpos( $adresa, "@");
ABD
if ( $poz === false )
echo "<P> Adresa de e-mail este incorecta!<BR>";
else
{
$user = substr ( $adresa, 0, $poz );
$server = substr ( $adresa, $poz+1);
echo "<P> Adresa de mail ".$adresa." este corecta.<BR>";
echo "User = <B>".$user."</B> si server =
<B>".$server ."</B><BR>";
}
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a4114.php
ABD
Sintaxa acestei comenzi este:
int fopen( string numeFisier, int mod );
Functia returneaza un 'handler ' pentru fisierul deschis prin care programatorul
poate interactiona cu fisierul.Daca nu se reuseste deschiderea fisierului, functia
returneaza valoarea FALSE.
Numele fisierului este o cale prin care fisierul poate fi accesat. Exista trei situatii
posibile:
l
Serverul Web ruleaza sub Unix : calea catre fisier este data prin nume de
directoare despartite prin '/', spre exemplu "/tmp/a1.dat";
Serverul Web ruleaza sub Windows : calea catre fisier respecta conventia
Windows, cu dublarea caracterului '\' (caracter de control PHP) in cale,
spre exemplu "c:\\temp\\a1.dat";
Adresa este a unei resurse de pe un server HTTP sau FTP:
"http://server1.domeniu5.com/diretorulmeu/" sau
"ftp://utilizator:parola@serverftp.domeniu3.com/pub/fisier4.txt";
Daca numele este simplu (nu cuprinde nici o cale) fisierul se considera in
directorul unde se gaseste scriptul PHP.
Parametrul mod specifica modul in care se va prelucra fisierul. El este un sir
format din urmatoarele caractere:
mod efect
r
deschide strict in citire si pozitioneaza referinta la inceputul fisierului
r+ deschide in citire / scriere si pozitioneaza referinta la inceputul fisierului
deschide doar in scriere si pozitioneaza referinta la inceput, trunchiind fisierul;
w
daca fisierul nu exista va fi creat
deschide doar in scriere /citire si pozitioneaza referinta la inceput, trunchiind fisierul;
w+
daca fisierul nu exista va fi creat
deschide doar in scriere si pozitioneaza referinta la sfarsitul fisierului,
a
permitand adaugarea; daca fisierul nu exista va fi creat
deschide doar in scriere /citire si pozitioneaza referinta la sfarsitul fisierului,
a+
permitand adaugarea; daca fisierul nu exista va fi creat
Pe langa caracterele precizate se mai poate adauga caracterul 'b' specificand
accesul in mod binar la informatiile din fisier, ex. "wb". Implicit informatiile sunt
privite ca fiind texte despartite prin caracterul linie noua '\n'.
Dupa folosirea unui fisier, acesta trebuie inchis. In acest scop se foloseste
functia fclose. Sintaxa sa este:
bool fclose ( int fp );
Parametrul fp este un handler al unui fisier deschis prin functia fopen. Daca
fclose nu poate inchide fisierul, functia returneaza valoarea FALSE.
106
ABD
ABD
string fgets ( int fp, [int lungime]);
Linia citita va avea lungimea data de parametrul lungime daca nu se intalneste
mai intai caracterul de linie noua '\n' sau sfarsitul de fisier (eof). Daca
parametrul nu este specificat se va conisdera la valoarea implicita 1024 (1KO).
Exemplu de citire a tuturor liniilor dintr-un fisier folosind fgets:
$fd = fopen ("inputfile.txt", "r");
while (!feof ($fd)) {
$sir = fgets($fd, 4096);
echo $sir;
}
fclose ($fd);
Daca se doreste copierea pur si simplu a textului dintr-un fisier in pagina
generata se poate folosi mai eficient functia readfile. Ea are prototipul:
int readfile ( string numeFisier );
Functia returneaza numarul de caractere citite corect sau FALSE daca a aparut o
eroare. De remarcat faptul ca, spre deosebire de functiile anterioare, readfile
primeste direct numele unui fiser si nu necesita deschiderea acestuia in
prealabil cu ajutorul lui fopen.
Functia file este asemanatoare cu functia prezentata anterior dar, spre
deosebire de readfile, nu copiaza continutul fisierului in pagina generata ci il
plaseaza intr-un tablou. Fiecare intrare in tablou va contine cate o linie de text,
linie incheiata cu caracterul '\n' (acesta apare in tablou). Sintaxa sa este:
array file ( string numeFisier );
108
ABD
Functia unlink sterge un fisier specificat prin numele sau. Daca stergerea
reuseste returneaza TRUE, FALSE in caz contrar.
bool file_exists ( string fisier);
Functia file_exists permite testarea existentei unui fisier specificat prin numele
sau. Testarea se face fara deschiderea fisierului.
int feof ( int fp );
Functia feof este utila in determinarea sfarsitului de fisier la parcurgerea
iterativa a acestuia. Functia returneaza TRUE daca s-a ajuns la sfarsitul
fisierului.
int filesize ( string fisier );
Functia filesize returneaza dimensiunea in octeti a unui fisier dat prin nume. In
caz de eroare intoarce FALSE. Nu se poate afla dimensiunea unui fisier care nu
este local (peste FTP sau HTTP).
int fseek ( int fp, int deplasament [, int deUnde] );
Functia fseek permite pozitionarea pe o anumita pozitie in fisier. Are sens doar
daca informatia este structurata. Deplasamentul se specifica in octeti. Pozitia
din care acesta se calculeaza este specificata de parametrul deUnde care poate
avea valorile: SEEK_SET (fata de inceputul fisierului), SEEK_CUR (fata de
pozitia curenta), SEEK_END (fata de sfarsitul fisierului). Daca parametrul
deUnde nu este specificat se considera implicit SEEK_SET.
int flock ( int fp, int operatie);
Functia flock permite blocarea accesului la un anumit fisier dintr-un script PHP.
Acest lucru este necesar pentru a nu permite ca doua procese sa acceseze
simultan continutul unui fisier, in cazul in care cel putin unul dintre ele modifica
fisierul. Tipul blocarii accesului se specifica prin parametrul operatie:
operatie efect
blocare de citire (reading lock).
1
Fisierul poate fi accesat de altii pentru citire dar nu si pentru scriere.
blocare de scriere (writing lock).
2
Fisierul nu mai poate fi accesat de nimeni altcineva.
3
Eliberare blocare (atat de citire cat si de scriere)
prin adaugarea valorii 4 la valorile anterioare functia flock nu se va
+4
bloca in cazul in care nu a putut obtine accesul ci va returna imediat FALSE.
Exemplu de blocare la scriere:
$fp = fopen ( "comenzi.dat","w");
flock ( $fp, 2); // blocare de scriere
109
ABD
fwrite ( $fp, $comanda );
flock ( $fp, 3); // eliberare blocare
fclose ( $fp);
Creati fisierul a4124.php pentru afisarea unui contor simplu de
accese in pagina.
<HTML>
<HEAD><TITLE>Activitate 4.1.2.4</TITLE></HEAD>
<BODY>
<?php
Activitate
5
110
ABD
[site1]
12
[siteulMeu]
56
...
Fiecare site va avea o intrare cu numele sau intre paranteze drepte '[' si ']' pe o
linie si cu valoarea contorului corespunzator pe linia urmatoare.
Functia va incrementa doar contorul corespunzator numelui transmis. Daca
functia incrementeazaContor nu gaseste o intrare corespunzatoare numelui
transmis, va crea o astfel de intrare si o va initializa cu 1.
Scrieti apoi o pagina care foloseste acest program pentru a afisa un contor.
Raspunsul la aceasta tema va consta in numele celor doua fisiere si observatiile
referitoare la problemele intampinate, fisierele urmand sa fie transmise prin email la adresa dan@cs.upt.ro.
<< Cuprins
'2010 conf. ing. Dan Pescaru
111
ABD
Cap. 17 PHP si MySQL
4.2.1. MySQL. Limbajul SQL
4.2.1.1. Baze de date. Tabele
4.2.1.2. Utilizatori si privilegii
4.2.1.3. Adaugarea, modificarea si stergerea datelor
4.2.1.4. Interogari SELECT
4.2.2. Utilizarea unei baze de date mySQL in PHP
4.2.2.1. Conectarea la server
4.2.2.2. Adaugarea de informatii
4.2.2.3. Cautarea si afisarea rezultatelor
4.2.3. Tema 4.b
112
ABD
Pentru a crea o baza de date mySQL se va folosi comanda:
mysql> CREATE DATABASE nume_db;
Pentru a sterge o baza de date mySQL care nu mai este necesara se va folosi comanda:
mysql> DROP DATABASE nume_db;
Pentru selectarea unei baze de date se va folosi comanda USE . Prin aceasta se stabileste baza de
date in contextul careia se vor executa interogarile ulterioare. Ea se va numi baza de date
activa.
Sintaxa acestei comenzi este:
mysql> USE nume_db;
Datele retinute sunt organizate de o baza de date in tabele . Pentru a crea o tabela se va utiliza
comanda CREATE TABLE . Aceasta are sintaxa:
mysql> CREATE [TEMPORARY] TABLE tbl_name [(create_definition,...)];
TEMPORARY - specifica crearea unei tabele temporare care va fi stearsa automat la inchiderea
conexiunii in care a fost creata; doua conexiuni pot crea doua tabele temporare cu aceleasi nume,
ele nu vor interfera.
create_definition - pentru definirea coloanelor este un sir de tipul:
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [PRIMARY
KEY]
PRIMARY KEY - specifica cheia primara pentru tabela. Un singur camp din tabela poate avea
acest parametru. Coloana declarata ca si cheie primara este indexata automat. Daca tabela are
cheia primara formata din mai multe campuri, aceasta va trebui specificata separat, pe post de
camp suplimentar, cu sintaxa "primary key (camp1, camp2 ...)".
Pentru a sterge o tabela se va folosi comanda:
mysql> DROP TABLE tbl_name;
113
ABD
mysql> GRANT privilegii [coloane] ON componenta TO nume_utilizator [IDENTIFIED BY 'parola']
[WITH GRANT OPTINS ]
Pentru mai multe informatii se poate consulta documentatia de la adresa:
http://www.mysql.com/documentation/index.html
114
ABD
ALL, implicit se considera ALL.
expresie_de_selectie - expresia de selectie poate cuprinde referinte la coloane sau la functii
aplicate asupra acestora. Un caz special il reprezinta caracterul * care semnifica includerea tuturor
coloanelor din tabela in rezultat.
FROM referinte_tabele - specifica tabela sau tabelele din care se selecteaza datele. In cazul in
care referinta cuprinde mai multe tabele operatia este una de JOIN.
WHERE conditie_selectie - specifica conditia de includere a datelor in selectie. Permite selectia
doar a datelor care intereseaza la un moment dat. In cazul operatiunii de JOIN aici se vor adauga
si constrangerile date de relatiile dintre tabele. Conditia de selectie consta dintr -o expresie logica
simpla sau complexa care poate cuprinde operatori si functii.
ORDER BY {intreg_pozitiv | nume_col | formula} [ASC | DESC], ... - permite ordonarea
rezultatului dupa anumite coloane sau formule. Daca se specifica o lista de numere, acestea vor fi
interpretate ca numere de ordine a coloanelor specificate in SELECT (incepand cu 1). Ordonarea se
face dupa prima coloana din lista. In cazul in care doua inregistari au aceiasi valoare pentru
coloana respectiva se va lua in considerare a doua coloana din lista (daca este specificata) etc.
Parametrii ASC si DESC specifica ordonarea crescatoare, respectiv descrescatoare a inregistrarilor
in rezultat.
Din clientul de mySQL rulati secveta pentru crearea bazei de date biblioteca:
Activitate
1
115
ABD
l
l
Cautarea unei informatii in fisier necesita un timp mare si diverse artificii de programare
Apar probleme la accesul concurent asupra fisierelor care pot ingreuna sau chiar bloca pentru
un timp indelungat accesul la site
La stergerea sau inserarea datelor in mijlocul fisierului acesta va trebui recopiat, ceea ce duce
la timpi inadmisibili de mari pentru prelucrari
Nivelul de securitate la accesul spre aceste fisiere este lasat exclusiv la latitudinea sistemului
de operare. In general este imposibil de asigurat chiar si un nivel minim de securitate.
Din motivele expuse reiese necesitatea de a utiliza baze de date in locul unor simple fisiere pentru
a asigura stocarea si regasirea eficienta a datelor aplicatiei.
Utilizand combinatia PHP+mySQL se pot scrie adevarate aplicatii de baze de date cu interfata Web.
Cele mai comune implementari raman totusi cele specifice Internetului: magazine virtuale,
forumuri de discutii, portaluri de e -mail etc.
116
ABD
parola - este un sir de caractere cuprinzand parola in clar a utilizatorului specificat. Deoarece
liniile php nu traverseza serverul Web, aceasta parola nu poate fi citita de utilizator prin comanda
View Source a navigatorului Web. Singura problema apare daca cineva neautorizat are acces local
la sistemul de fisere de pe server si poate citi direct fisierul php.
Ambele comenzi returneaza conexiunea daca totul este ok si valoarea FALSE daca nu se poate
stabili legatura. O secventa tipica de apel este:
@ $bd = mysql_connect( "localhost", "utilizator403", "parola.403");
if( !$bd )
die("Server ocupat. Reveniti peste 1 ora!");
Pentru inchiderea conexiunii, dupa ce nu mai este necesara, se va utiliza comanda:
bool mysql_close ( resource identificatorBD );
Parametrul identificatorBD trebuie sa fie un identificator valid de conexiune returnat in prealabil de
comada mysql_connect (sau mysql_pconnect).
Dupa realizarea unei conexiuni, pentru a putea accesa datele din tabelele unei anumite baze de
date de pe server, aceasta trebuie selectata prin comanda mysql_select_db :
bool mysql_select_db ( string numeBazaDeDate );
117
BD
<FORM name="formEdi" method="post" action="a4222.php" >
<P>Adaugare EDITURA
<P>Cod editura <INPUT type="text" name="codEdi" size ="3"
maxlength ="3" ><BR>
Denumire <INPUT type="text" name="numeEdi" size="64"
maxlength ="64"><BR>
Adresa <INPUT type="text" name="adrEdi" size ="64" maxlength="64"><BR>
Telefon <INPUT type="text" name="telEdi" size ="24" maxlength="24"><BR>
<P> < INPUT type="submit" name="trimit" value="Submit" >
<INPUT type="reset" name="sterg" value ="Reset">
</FORM>
</BODY>
</HTML>
Creati fisierul a4222.php cu urmatorul continut:
Activitate
2
<HTML>
<HEAD>
<TITLE> Adaugare editura </TITLE>
</HEAD>
<BODY>
<H1> Prelucrare date din formularul a4222.html</H1>
<HR>
<?php
$codEdi = addslashes ( trim ( $HTTP_POST_VARS["codEdi"] ) );
$numeEdi = addslashes ( trim ( $HTTP_POST_VARS["numeEdi"] ) );
$adrEdi = addslashes ( trim ( $HTTP_POST_VARS["adrEdi"] ) );
$telEdi = addslashes ( trim ( $HTTP_POST_VARS["telEdi"] ) );
echo "Cod editura: " .$codEdi."<BR>";
echo "Nume editura: ".$numeEdi."<BR>";
echo "Adresa editura: " .$adrEdi."<BR>";
echo "Telefon editura: " .$telEdi ."<BR>";
if($codEdi=="" or $numeEdi=="")
die("Nu sa compeltat codul si numele editurii!");
@ $bd = mysql_connect( "localhost", "webcititor", "pAroLA!");
if( !$bd )
die("Nu s-a putut realiza conexiunea cu mySQL!");
mysql_select_db ( "Biblioteca" );
$interogare = "INSERT INTO Edituri VALUES (\"$ codEdi\", ";
$interogare .= "\" $numeEdi\", \" $adrEdi \", ";
$interogare .= "\" $telEdi\" )";
echo "<P> Interogarea rezultata: ".$interogare ."<BR>";
$rez = mysql_query ($interogare);
if ( !$rez)
die("Eroare la adaugare!");
echo "Adaugare reusita. Inregistrari adaugate: ".mysql_affected_rows() ."<BR>";
mysql_close ($bd);
?>
<HR>
</BODY>
</HTML>
Copiati fisierele in directorul htdocs al serverului de Web si incarcati adresa
http://localhost/a4222.html. Completati formularul si apasati apoi butonul Submit.
Observatie: serverul mysql trebuie sa fie pornit.
118
ABD
transmitere a unor astfel de interogari este asemanatoare cu cea pentru interogari actiune,
prezentata in capitolul anterior. Diferenta majora la interogarile de tip SELECT consta in
necesitatea de a afisa rezultatul interogarii.
In urma rularii unei interogari de cautare se va folosi functia mysql_num_rows pentru a afla
numarul de inregistrari din rezultat. Acestei functii i se va transmite ca si parametru referinta
rezultata in urma apelului functiei mysql_query.
Exista trei metode diferite de a interpreta si prelucra rezultatul unei interogari SELECT:
1. Rezultatul este preluat prin functia mysql_fetch_array si interpretat ca un tablou asociativ.
Acest tablou are ca si chei numele coloanelor selectate iar ca si valori, valorile corespondente din
rezultat. Fiecare apel succesiv al functiei mysql_fetch_array va returna urmatoarea inregistrare din
rezultat. Cand nu mai sunt disponibile inregistrari, functia va retuna valoarea FALSE.
2. Rezultatul este preluat prin functia mysql_fetch_row si interpretat ca un tablou indexat numeric.
Acest tablou are ca si indexi numerele 0,1,2 etc. iar ca si valori, valorile corespondente coloanelor
de pe pozitiile respective din rezultat. Fiecare apel succesiv al functiei mysql_fetch_row va returna
urmatoarea inregistrare din rezultat. Cand nu mai sunt disponibile inregistrari, functia va retuna
valoarea FALSE.
3. Rezultatul este preluat prin functia mysql_fetch_object si interpretat ca un obiect. Acest obiect
are ca si atribute numele coloanelor selectate iar ca si valori ale acestora, valorile corespondente
din rezultat. Fiecare apel succesiv al functiei mysql_fetch_object va returna urmatoarea
inregistrare din rezultat. Cand nu mai sunt disponibile inregistrari, functia va retuna valoarea
FALSE.
De obicei la prelucrarea rezultatelor unei interogari SELECT se vor genera liste sau tablouri HTML.
119
ABD
die ("Nu s-a putut realiza conexiunea cu mySQL!");
mysql_select_db ( "Biblioteca" );
$interogare = "SELECT * FROM Edituri ";
if ( $numeEdi!="")
$interogare .= "WHERE nume LIKE \"$numeEdi%\"";
echo "<P> Interogarea rezultata: ".$interogare ."<BR>";
$rez = mysql_query ($interogare);
if (!$rez)
die ("Eroare la cautare!");
$nrRez = mysql_num_rows ( $rez );
if($nrRez == 0)
echo "Nu s-a gasit nici o editura!";
else
{
echo "S-au gasit $nrRez edituri:<BR>";
echo "<TABLE BORDER=1>";
echo
Activitate "<TR><TD>Cod</TD><TD>Nume</TD><TD>Adresa</TD><TD>Tel</TD></TR>";
3
for($i=0; $i<$nrRez; $i++ ) {
$ed = mysql_fetch_object($rez);
echo "<TR><TD>".$ed ->cod_editura ."</TD>";
echo "<TD>".$ed ->nume ."</TD>";
echo "<TD>".$ed ->adresa."</TD>";
echo "<TD>".$ed ->telefon."</TD></TR>";
}
echo "</TABLE>";
}
mysql_close ($bd);
?>
<HR>
</BODY>
</HTML>
Copiati fisierele in directorul htdocs al serverului de Web si incarcati adresa
http://localhost/a4223.html. Completati formularul si apasati apoi butonul Submit.
Observatie: serverul mysql trebuie sa fie pornit.
120
ABD
Pentru a crea o baza de date mySQL se va folosi comanda:
mysql> CREATE DATABASE nume_db;
Pentru a sterge o baza de date mySQL care nu mai este necesara se va folosi comanda:
mysql> DROP DATABASE nume_db;
Pentru selectarea unei baze de date se va folosi comanda USE . Prin aceasta se stabileste baza de
date in contextul careia se vor executa interogarile ulterioare. Ea se va numi baza de date
activa.
Sintaxa acestei comenzi este:
mysql> USE nume_db;
Datele retinute sunt organizate de o baza de date in tabele . Pentru a crea o tabela se va utiliza
comanda CREATE TABLE . Aceasta are sintaxa:
mysql> CREATE [TEMPORARY] TABLE tbl_name [(create_definition,...)];
TEMPORARY - specifica crearea unei tabele temporare care va fi stearsa automat la inchiderea
conexiunii in care a fost creata; doua conexiuni pot crea doua tabele temporare cu aceleasi nume,
ele nu vor interfera.
create_definition - pentru definirea coloanelor este un sir de tipul:
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [PRIMARY
KEY]
PRIMARY KEY - specifica cheia primara pentru tabela. Un singur camp din tabela poate avea
acest parametru. Coloana declarata ca si cheie primara este indexata automat. Daca tabela are
cheia primara formata din mai multe campuri, aceasta va trebui specificata separat, pe post de
camp suplimentar, cu sintaxa "primary key (camp1, camp2 ...)".
Pentru a sterge o tabela se va folosi comanda:
mysql> DROP TABLE tbl_name;
121
ABD
mysql> GRANT privilegii [coloane] ON componenta TO nume_utilizator [IDENTIFIED BY 'parola']
[WITH GRANT OPTINS ]
Pentru mai multe informatii se poate consulta documentatia de la adresa:
http://www.mysql.com/documentation/index.html
122
ABD
ALL, implicit se considera ALL.
expresie_de_selectie - expresia de selectie poate cuprinde referinte la coloane sau la functii
aplicate asupra acestora. Un caz special il reprezinta caracterul * care semnifica includerea tuturor
coloanelor din tabela in rezultat.
FROM referinte_tabele - specifica tabela sau tabelele din care se selecteaza datele. In cazul in
care referinta cuprinde mai multe tabele operatia este una de JOIN.
WHERE conditie_selectie - specifica conditia de includere a datelor in selectie. Permite selectia
doar a datelor care intereseaza la un moment dat. In cazul operatiunii de JOIN aici se vor adauga
si constrangerile date de relatiile dintre tabele. Conditia de selectie consta dintr -o expresie logica
simpla sau complexa care poate cuprinde operatori si functii.
ORDER BY {intreg_pozitiv | nume_col | formula} [ASC | DESC], ... - permite ordonarea
rezultatului dupa anumite coloane sau formule. Daca se specifica o lista de numere, acestea vor fi
interpretate ca numere de ordine a coloanelor specificate in SELECT (incepand cu 1). Ordonarea se
face dupa prima coloana din lista. In cazul in care doua inregistari au aceiasi valoare pentru
coloana respectiva se va lua in considerare a doua coloana din lista (daca este specificata) etc.
Parametrii ASC si DESC specifica ordonarea crescatoare, respectiv descrescatoare a inregistrarilor
in rezultat.
Din clientul de mySQL rulati secveta pentru crearea bazei de date biblioteca:
Activitate
1
123
ABD
l
l
Cautarea unei informatii in fisier necesita un timp mare si diverse artificii de programare
Apar probleme la accesul concurent asupra fisierelor care pot ingreuna sau chiar bloca pentru
un timp indelungat accesul la site
La stergerea sau inserarea datelor in mijlocul fisierului acesta va trebui recopiat, ceea ce duce
la timpi inadmisibili de mari pentru prelucrari
Nivelul de securitate la accesul spre aceste fisiere este lasat exclusiv la latitudinea sistemului
de operare. In general este imposibil de asigurat chiar si un nivel minim de securitate.
Din motivele expuse reiese necesitatea de a utiliza baze de date in locul unor simple fisiere pentru
a asigura stocarea si regasirea eficienta a datelor aplicatiei.
Utilizand combinatia PHP+mySQL se pot scrie adevarate aplicatii de baze de date cu interfata Web.
Cele mai comune implementari raman totusi cele specifice Internetului: magazine virtuale,
forumuri de discutii, portaluri de e -mail etc.
124
ABD
parola - este un sir de caractere cuprinzand parola in clar a utilizatorului specificat. Deoarece
liniile php nu traverseza serverul Web, aceasta parola nu poate fi citita de utilizator prin comanda
View Source a navigatorului Web. Singura problema apare daca cineva neautorizat are acces local
la sistemul de fisere de pe server si poate citi direct fisierul php.
Ambele comenzi returneaza conexiunea daca totul este ok si valoarea FALSE daca nu se poate
stabili legatura. O secventa tipica de apel este:
@ $bd = mysql_connect( "localhost", "utilizator403", "parola.403");
if( !$bd )
die("Server ocupat. Reveniti peste 1 ora!");
Pentru inchiderea conexiunii, dupa ce nu mai este necesara, se va utiliza comanda:
bool mysql_close ( resource identificatorBD );
Parametrul identificatorBD trebuie sa fie un identificator valid de conexiune returnat in prealabil de
comada mysql_connect (sau mysql_pconnect).
Dupa realizarea unei conexiuni, pentru a putea accesa datele din tabelele unei anumite baze de
date de pe server, aceasta trebuie selectata prin comanda mysql_select_db :
bool mysql_select_db ( string numeBazaDeDate );
125
ABD
<FORM name="formEdi" method="post" action="a4222.php" >
<P>Adaugare EDITURA
<P>Cod editura <INPUT type="text" name="codEdi" size ="3"
maxlength ="3" ><BR>
Denumire <INPUT type="text" name="numeEdi" size="64"
maxlength ="64"><BR>
Adresa <INPUT type="text" name="adrEdi" size ="64" maxlength="64"><BR>
Telefon <INPUT type="text" name="telEdi" size ="24" maxlength="24"><BR>
<P> < INPUT type="submit" name="trimit" value="Submit" >
<INPUT type="reset" name="sterg" value ="Reset">
</FORM>
</BODY>
</HTML>
Creati fisierul a4222.php cu urmatorul continut:
Activitate
2
<HTML>
<HEAD>
<TITLE> Adaugare editura </TITLE>
</HEAD>
<BODY>
<H1> Prelucrare date din formularul a4222.html</H1>
<HR>
<?php
$codEdi = addslashes ( trim ( $HTTP_POST_VARS["codEdi"] ) );
$numeEdi = addslashes ( trim ( $HTTP_POST_VARS["numeEdi"] ) );
$adrEdi = addslashes ( trim ( $HTTP_POST_VARS["adrEdi"] ) );
$telEdi = addslashes ( trim ( $HTTP_POST_VARS["telEdi"] ) );
echo "Cod editura: " .$codEdi."<BR>";
echo "Nume editura: ".$numeEdi."<BR>";
echo "Adresa editura: " .$adrEdi."<BR>";
echo "Telefon editura: " .$telEdi ."<BR>";
if($codEdi=="" or $numeEdi=="")
die("Nu sa compeltat codul si numele editurii!");
@ $bd = mysql_connect( "localhost", "webcititor", "pAroLA!");
if( !$bd )
die("Nu s-a putut realiza conexiunea cu mySQL!");
mysql_select_db ( "Biblioteca" );
$interogare = "INSERT INTO Edituri VALUES (\"$ codEdi\", ";
$interogare .= "\" $numeEdi\", \" $adrEdi \", ";
$interogare .= "\" $telEdi\" )";
echo "<P> Interogarea rezultata: ".$interogare ."<BR>";
$rez = mysql_query ($interogare);
if ( !$rez)
die("Eroare la adaugare!");
echo "Adaugare reusita. Inregistrari adaugate: ".mysql_affected_rows() ."<BR>";
mysql_close ($bd);
?>
<HR>
</BODY>
</HTML>
Copiati fisierele in directorul htdocs al serverului de Web si incarcati adresa
http://localhost/a4222.html. Completati formularul si apasati apoi butonul Submit.
Observatie: serverul mysql trebuie sa fie pornit.
126
ABD
transmitere a unor astfel de interogari este asemanatoare cu cea pentru interogari actiune,
prezentata in capitolul anterior. Diferenta majora la interogarile de tip SELECT consta in
necesitatea de a afisa rezultatul interogarii.
In urma rularii unei interogari de cautare se va folosi functia mysql_num_rows pentru a afla
numarul de inregistrari din rezultat. Acestei functii i se va transmite ca si parametru referinta
rezultata in urma apelului functiei mysql_query.
Exista trei metode diferite de a interpreta si prelucra rezultatul unei interogari SELECT:
1. Rezultatul este preluat prin functia mysql_fetch_array si interpretat ca un tablou asociativ.
Acest tablou are ca si chei numele coloanelor selectate iar ca si valori, valorile corespondente din
rezultat. Fiecare apel succesiv al functiei mysql_fetch_array va returna urmatoarea inregistrare din
rezultat. Cand nu mai sunt disponibile inregistrari, functia va retuna valoarea FALSE.
2. Rezultatul este preluat prin functia mysql_fetch_row si interpretat ca un tablou indexat numeric.
Acest tablou are ca si indexi numerele 0,1,2 etc. iar ca si valori, valorile corespondente coloanelor
de pe pozitiile respective din rezultat. Fiecare apel succesiv al functiei mysql_fetch_row va returna
urmatoarea inregistrare din rezultat. Cand nu mai sunt disponibile inregistrari, functia va retuna
valoarea FALSE.
3. Rezultatul este preluat prin functia mysql_fetch_object si interpretat ca un obiect. Acest obiect
are ca si atribute numele coloanelor selectate iar ca si valori ale acestora, valorile corespondente
din rezultat. Fiecare apel succesiv al functiei mysql_fetch_object va returna urmatoarea
inregistrare din rezultat. Cand nu mai sunt disponibile inregistrari, functia va retuna valoarea
FALSE.
De obicei la prelucrarea rezultatelor unei interogari SELECT se vor genera liste sau tablouri HTML.
127
ABD
die ("Nu s-a putut realiza conexiunea cu mySQL!");
mysql_select_db ( "Biblioteca" );
$interogare = "SELECT * FROM Edituri ";
if ( $numeEdi!="")
$interogare .= "WHERE nume LIKE \"$numeEdi%\"";
echo "<P> Interogarea rezultata: ".$interogare ."<BR>";
$rez = mysql_query ($interogare);
if (!$rez)
die ("Eroare la cautare!");
$nrRez = mysql_num_rows ( $rez );
if($nrRez == 0)
echo "Nu s-a gasit nici o editura!";
else
{
echo "S-au gasit $nrRez edituri:<BR>";
echo "<TABLE BORDER=1>";
echo
Activitate "<TR><TD>Cod</TD><TD>Nume</TD><TD>Adresa</TD><TD>Tel</TD></TR>";
3
for($i=0; $i<$nrRez; $i++ ) {
$ed = mysql_fetch_object($rez);
echo "<TR><TD>".$ed ->cod_editura ."</TD>";
echo "<TD>".$ed ->nume ."</TD>";
echo "<TD>".$ed ->adresa."</TD>";
echo "<TD>".$ed ->telefon."</TD></TR>";
}
echo "</TABLE>";
}
mysql_close ($bd);
?>
<HR>
</BODY>
</HTML>
Copiati fisierele in directorul htdocs al serverului de Web si incarcati adresa
http://localhost/a4223.html. Completati formularul si apasati apoi butonul Submit.
Observatie: serverul mysql trebuie sa fie pornit.
128
ABD
Cap 18. Aplicatii E-Comerce
5.1.1. Tipuri de aplicatii e-comerce
5.1.1.1. Brosuri de prezentare
5.1.1.2. Comenzi prin Internet pentru marfuri si servicii
5.1.1.3. Comert cu servicii si bunuri digitale
5.1.1.4. Aplicatii de tip "valoare adaugata"
5.1.2. Riscuri si probleme legate de aplicatiile e-comerce
5.1.3. Tema 5.a
ABD
implementarii (in multe situatii limbajul HTML este suficient) ci mai degraba
sunt probleme legate de marketing:
l
l
l
l
l
ABD
pe Web trebuie sa fie neperisabil, simplu de livrat, suficient de scump
comparativ cu pretul livrarii dar nu intr-atat incat sa depaseasca pragul
psihologic care cere o examinare directa inainte de cumparare. Exemple de
astfel de produse care se vand deja cu succes pe Web sunt: carti si reviste,
calculatoare si produse software, echipamente electonice de uz casnic,
imbracaminte, muzica, bilete la diverse evenimente sau bilete de calatorii sau
odihna. In general produsele "fara personalitate" se vand mult mai usor pe Web
decat cele "cu personalitate". Spre exemplu, doua exemplare din aceiasi carte
sunt virtual identice pe cand doi pepeni difera, chiar daca sunt de aceiasi gen.
Pentru a putea convinge un cumparator, un site de comenzi on-line trebuie sa
asigure un minim de conditii: produsele trebuie sa fie de incredere (este dificil
de vandut o marca despre care nu a mai auzit nimeni), trebuie oferita
posibilitatea de a returna produsul intr-un interval de timp rezonabil daca
acesta nu satisface, formularul pentru cumparare trebuie sa fie clar si simplu de
folosit, site-ul trebuie sa fie compatibil cu diverse navigatoare si sisteme de
operare (un cumparator nu va schimba navigatorul preferat doar pentru a putea
vizualiza site-ul respectiv).
ABD
altor servicii si nu aduce el insusi profit imediat. Un alt exemplu, de data
aceasta acoperind mai multe domenii, de la transport pana la domeniul bancar,
este FEDEX (www.fedex.com). El este menit doar sa adauge valoare unor
servicii oferite in maniera conventionala de compania in cauza.
Posibilitatea clientilor de a urmari drumul unui colet (la UPS) sau de a-si
consulta pe Web balanta bancara asigura in general un avantaj cometitiv
companiilor respective.
Site-urile gen "forum de suport" pot fi include de asemenea in aceasta
categorie. Aceste forumuri sunt menite facilitarii unor discutii intre clienti despre
anumite produse sau probleme aparute la folosirea acelor produse. In felul
acesta se asigura de fapt asistenta tehnica la cel mai scazut cost posibil atat
pentru client, care poate apela direct la solutiile oferite de alti participanti fara a
fi nevoie de telefoane internationale la un service, cat mai ales pentru ofertant,
care nu asigura decat un moderator al acestor discutii.
Activitate
1
Crackeri
Riscul unui impact minor pe piata
Caderi hardware
Erori software
Probleme cu liniile de comunicatii
Neclaritati in legislatie
Limite fizice ale sistemelor
Atacurile crackerilor sunt cele mai mediatizate riscuri ale afacerilor e-comerce.
Crackerii sunt specialisti in calculatoare rau intentionati. Activitatea lor se
incadreaza in ceea ce politia denumeste "criminalitate electronica". Crackerii
ataca un site comercial pentru a castiga prestigiu, pentru a-si demostra
abilitatile, pentru a sabota o afacere sau pentru a fura bani sau bunuri oferite
132
ABD
pe Web. Pentru a limita pierderile determinate de aceste atacuri, cele mai utile
masuri sunt: pastrarea unor copii de siguranta a tuturor datelor oferite pe
Internet, o politica justa in privinta salariatilor care sa nu determine
nemultumiri grave si dorinta de razbunare, utilizarea unui soft sigur si
actulizarea lui permanenta, examinarea zilnica a activitatii si jurnalelor de
tranzacti.
Tinand cont de timpul si sumele mari implicate de dezvoltarea unei afaceri ecomerce de dimensiune medie sau mare, un risc major il reprezinta calculul
gresit al perioadei de amortizare, strict legata de evaluarea impactului pe care
site-ul il va avea dupa lansare. Acest impact se masoara de obicei in numar
total de vizitatori pe o perioada stabilita de timp sau, mai precis in numar de
vizitatori raportati la segmentele de cumparatori avute in calcul.
Este evident faptul ca, din moment ce toata afacerea se bazeaza pe rularea
unor programe specifice pe calculatoare ruland servere de Web, de baze de
date, de e -mail etc. , caderea fizica (hardware) a unui astfel de calculator duce
la blocarea afacerii. Din acest motiv, un important accent se pune pe asigurarea
unor servicii redundante, astfel incat, la caderea unui server, altul de rezerva sa
ii poata lua locul in cel mai scurt timp. Problema aici este legata de costul mare
a suportului hardware relativ la costul total al afacerii.
Este in general acceptat de asemena ca orice produs software complex are
intrinsec o serie de erori (bug-uri) foarte greu de descoperit si remediat. Din
acest motiv, pe de o parte trebuie cumparate sisteme de operare si softuri tip
server de incredere, iar pe de alta parte trebuie asigurat un proces serios de
testare a programelor proprii (dezvoltate in HTML, JavaScript, PHP, SQL etc.)
Datorita faptului ca afacerea se bazeaza pe conexiunea la Internet, este evident
ca alegerea unui serviciu de conectare cat mai sigur si eficient este esentiala. In
acest sens trebuie avute in vedere largimea de banda reala oferita cat si de
reputatia companiei ISP referitor la siguranta serviciilor. Daca nu este posibil
(din cauza costurilor) asigurarea a cel putin doua cai separate de conectarea se
va tine cont de includerea in contractul cu ISP a unor clauze privitoare la
recuperarea daunelor provocate de intreruperea conexiunii peste o anumita
limita de timp sau frecventa pe an.
Un capitol greu controlabil este legat de lacunele care exista peste tot in lume
legate de legislatia in domeniul e-comerce. Aceste lacune sunt perfect
explicabile tinand cont de vechimea relativ mica a unor astfel de afaceri. Partea
incurajatoare este data de faptul ca se fac eforturi sustinute pentru inlaturarea
acestor probleme. Din acest motiv este important sa se supravegheze continu
modificarile legislatiei si sa se tina cont de eventuale taxe care pot apare in
legatura cu cele existente deja in domeniul afacerilor conventionale.
Un ultim aspect discutat se refera la limitele fizice ale sistemelor de calcul.
Pentru o afacere pe Internet este foarte important timpul de raspuns la o cerere
si disponibilitatea serviciilor 24 ore din 24 si 7 zile din 7. Problema aici consta in
a gandi sistemul de la inceput pentru o buna scalabilitate (posibilitate de
extindere) la preturi rezonabile. Limitarile avute in vedere se refera atat la
133
ABD
largimea de banda a conexiunilor la Internet cat si la puterea de calcul oferita
de calculatoarele server.
134
ABD
Cap. 19 Securitate
5.2.1. Utilizare cookies
5.2.1.1. Restrictii legate de cookies
5.2.1.2. Utilizare cookies in PHP
5.2.1.3. Probleme la folosirea cookies
5.2.2. Probleme de securitate la site-urile PHP
5.2.2.1. Securitatea serverului de Web
5.2.2.2. Securitatea instalarii PHP
5.2.3. Gestiunea utilizatorilor in PHP
5.2.3.1. Autentificarea utilizand serverul de Web
5.2.3.2. Autentificarea folosind PHP
5.2.4. Tema 5.b
ABD
Singura problema poate fi mentinerea unor informatii sensibile gen parole sau
conturi pe un calculator la care au acces mai multi utilizatori intre care
sistemul de operare nu asigura protectie.
Data expirarii este utilizata pentru ca navigatorul sa isi dea seama daca un
cookie este inca valid, si ca atare trebuie transmis serverului. Daca un cookie a
expirat, el nu va mai fi trimis catre server in nici o circumstanta. Daca timpul de
expirare nu este precizat, navigatorul va sterge automat cookie-ul la oprire.
Prin informatia despre calea valida se va stabili directorul de pe server pentru
care cookie-ul este activ. Daca pagina accesata nu provine din directorul
specificat (sau din subdirectoare ale acestuia), informatia din cookie nu va fi
transmisa serverului. Calea valida implicita este "/" care specifica orice director
de pe server.
Informatia despre domeniul valid stabileste serverele spre care acel cookie va fi
trimis. Informatia poate contine numele unui server (ex.
"www1.domeniulmeu.ro") sau numele unui domeniu (ex. ".domeniulmeu.ro")
caz in care sunt validate toate serverele din acel domeniu. Domeniul stabilit
implict este cel al servrului care seteaza acel cookie.
Parametrul referitor la transmiterea securizata impune navigatorului
transmiterea informatiei cookie doar daca conexiunea curenta este una
securizata (prin protocolul HTTPS). Daca parametrul nu este precizat, se va
trimite cookie-ul si pe conexiuni securizate si pe cele nesecurizate.
136
ABD
Functia returneaza adevarat daca s-a putut trimite acel cookie spre navigator si
fals in caz contrar. Daca functia returneaza adevarat nu inseamna insa ca acel
client a acceptat respectivul cookie. Un client poate refuza un cookie daca s-au
depasit limitele cantitative (300 sau 20) sau daca navigatorul este setat sa
refuze informatiile cookie.
Pentru a permite cererii de creare a cookie-ului sa fie transmisa catre server
trebuie ca apelul setcookie sa apara inaintea oricarei alte informatii trimise
clientului, chiar si inaintea unui simplu spatiu sau a tagurilor <HTML> sau
<HEAD>. Acest lucru este necesar deoarece datele pentru creare cookies sunt
impachetate in antetul raspunsului HTTP catre client, antet care se transmite
automat inaintea oricarei informatii care va aparea in pagina.
In cazul in care se doreste mentinerea mai multor date la client se vor crea mai
multe cookies. Dezavantajul acestei metode este legata de restrictia de maxim
20 de cookies / server. Pentru a evita acest lucru se poate apela la asocierea
valorilor multiple la un anumit cookie. Lucrul acesta este posibil daca se
apeleaza la tablouri in locul valorii singulare. Spre exemplu se poate folosi
secventa:
<?php
setcookie("preturi[0]",2000);
setcookie("preturi[1]",5000);
...
?>
Pentru a extinde durata de viata a unui cookie se poate trimite, prin intermediul
functiei setcookie , si termenul de expirare a lui. Timpul trebuie transmis ca si o
valoarea UNIX timestamp (numar de secunde scurs de la 01.01.1970). In PHP
exista doua functii pe baza carora se poate calcula un timestamp pentru o
anumita data. Prima este functia mktime care poate fi folosita pentru a calcula
date absolute (sintaxa: mktime( ore, min, sec, luna, zi, an ) ). A doua functie
este time care returneaza momentul curent in format timestamp . Utilizand time
se poate calcula o data relativa de expirare (ex. 30 de zile de la data curenta:
time()+30*24*60*60). O problema care apare relativ la data expirarii este
"timpul diferit" intre setarea cookie-ului (timpul de pe server) si timpul fata de
care navigatorul testeaza expirarea lui (timpul de pe calculatorul client).
<?php
$expira1 = mktime ( 0, 0, 0, 12, 30, 2004 ); // 30.12.2004, ora 0:00
$expira2 = time () + 3*30*24*60*60; // trei luni: 90 de zile de la data
curenta
setcookie("user", "Horia", $expira1);
setcookie("parola", "abcd", $expira2);
...
?>
In cazul acesta, navigatorul nu va mai distruge cookies la oprire. Ele vor fi
folosite pana cand expira si abia dupa aceea vor fi sterse.
137
ABD
In mod frecvent un server Web retine mai multe site-uri diferite. In acest caz se
creaza o serioasa bresa de securitate daca navigatorul trimite cookies setate de
un site catre paginile altui site de pe acelasi server. Pentru a evita acest lucru
se poate apela la parametrul "directorul valid" pentru un cookie. In acest caz,
informatiile cookies vor fi trimise doar paginilor care se gases in directoarele
care incep cu prefixul stabilit. Spre exemplu, pentru un director valid "/firma" se
va trimite informatia spre paginile "/firma1/pag1.php" si
"/firma2/formulare/f23.php", dar nu si spre "/firme/index.php":
setcookie("user", "Horia", $expira1, "/firmaMea/");
Tot in acest scop se poate limita numarul de servere spre care se transmite
cookies, prin precizarea "domeniului valid" al lor. Parametrul "domeniu valid"
poate cuprinde o singura masina (ex. "www.domeniulmeu.ro") sau mai multe
(ex. ".domeniulmeu.ro" este valid si pentru www.domeniulmeu.ro dar si pentru
hercules.domeniulmeu.ro etc.).
setcookie("user", "Horia", $expira1, "/firmaMea/", "www3.domeniulmeu.ro");
Daca in plus se doreste ca acel cookie sa fie trimis doar daca conexiunea este
una securizata (protocolul este HTTPS in locul protocolului HTTP standard).
Pentru a sterge un cookie fortat dintr-o pagina se poate apela functia setcookie
cu un singur parametru, si anume chiar numele cookie-ului respectiv. Trebuie
avut in vedere doar ca aceasta functie nu poate fi apelata decat la inceputul
paginii, inainte de orice iesire spre client.
setcookie("user") // sterge cookie-ul cu numele "user"
Pentru a folosi informatiile cookies intr-o pagina PHP, acestea pot fi accesate
prin intermediul tabloului $HTTP_COOKIE_VARS ["numeCookie"] (cau
$_COOKIE["numeCookie"] in PHP4). Spre exemplu se poate verifica daca un
cookie este primit sau nu prin secventa:
if ( !isset($HTTP_COOKIE_VARS ["utilizator"]) )
die ( "Acesati aceasta pagina pentru prima data! Va rugam sa va inregistrati
in prealabil." );
Observatie: un cookie nu este valabil in pagina care il seteaza ci doar in paginile
care vor fi incarcate ulterior.
ABD
O problema mai greu de rezolvat este aceea in care aplicatia depinde de
existenta informatiilor cookies, iar navigatorul clientului nu permite crearea
acestor informatii. Solutia evidenta in acest caz este cea care afiseaza un mesaj
de eroare prin care cere clientului sa schimbe optiunile navigatorului astfel incat
sa permita acceptarea informatiilor cookies. Testul acesta este in schimb
ingreunat de faptul ca in pagina curenta nu se poate determina daca
navigatorul a acceptat sau nu coockies. Solutia este setarea cookie de test si
apoi reicarcarea fortata a pagini cu ajutorul functiei header ("Location:
pagina_cutenta").
Creati fisierul a5213.php pentru a testa daca navigatorul accepta
sau nu cookies.
Activitate
1
<?php
// executia acestui script consta in doua faze:
// Faza 1: se trimite un setcookie si apoi se reincarca pagina
curenta
// Faza 2: se testeaza daca, dupa reincarcarea paginii,
informatia cookie exista
if ( !isset($HTTP_GET_VARS["test"])) {
// faza 1
$reincarca = "$PHP_SELF?test=1";
header("Location: $reincarca");
setcookie("cookieTest", "ok");
}
else
{
echo "<HTML>";
echo "<HEAD>";
echo "<TITLE>Activitate 5.2.1.3.</TITLE>";
echo "</HEAD>\n <BODY>";
if (!isset($HTTP_COOKIE_VARS["cookieTest"]))
die ( "Nu pot crea cookie. Va rugam scimbati optiunile
navigatorului!");
else {
// este ok. se poate redirecta spre pagina principala
// de ex: header( "Location: main.php" );
echo "Navigatorul accepta cookies";
echo "</BODY>\n</HTML>";
}
}
?>
Copiati fisierul in directorul htdocs al serverului de Web. Porniti
navigatorul si setati optiunile astfel incat sa nu accepte nici un
cookie. Incarcati adresa http://localhost/a5213.php si verificati
mesajul de eroare. Schimbati optiunile navigatorului ca sa
accepte cookies, reporniti navigatorul si apoi reincarcati pagina.
139
ABD
ABD
printr-o direciva Directory in fisiserul httpd.conf:
<Directory />
AllowOverride None
Options None
Order deny, allow
Deny from all
</Directory>
Dupa instalare, trebuie verificat ca aceasta directiva sa apara in fisierul de
configurare.
l
141
open_basedir
Aceasta optiune stabileste directoarele din care se pot accesa fisiere prin
functii PHP. Deoarece implicit optiunea stabileste directorul radacina al
serverului si, prin urmare sunt accesibile toate fisierele si directoarele
acesteia, ea se constituie intr-o serioasa lacuna de securitate. Daca
valoarea ei se stabileste la ".", vor putea fi accesate doar fisierele din
directorul curent al paginii sau subdirectoare ale acestuia.
memory_limit
Aceasta optiune limiteaza cantitatea de memorie (in octeti) pe care scripul
o poate utiliza. In felul acesta se poate evita ca un script sa ocupe prea
multe resurse de pe server. Implict valoarea este stabilita la 8Mo.
register_globals
Daca aceasta optiune este ON, toate datele care provin din exterior (din
ABD
formulare get sau post, din linia de adresa sau din cookies) sunt
transformate in variabile avand numele corespunzatoare. Acest lucru, desi
simplifica intr-o 0oarecare masura scrierea programelor, adauga o mare
supraincarcare la interpretarea scriptului precum si lacune mari de
securitate. O astfel de variabila poate fi suprascrisa destul de usor de catre
un hacker printr-un apel fals la pagina. In cazul in care optiunea este OFF,
datele se pot accesa prin tablourile sistem $HTTP_grup_VARS[] (grup
poate fi GET, POST, COOKIE, ENV etc.).
expose_php
Aceasta optiune trebuie stabilita pe OFF pentru ca sistemul sa nu ofere
direct informatii ca ruleaza o anumita versiune de PHP. Desi acest lucru nu
poate preveni un atac, il poate totusi intarzia.
142
ABD
Serverul Apache permite fortarea autentificarii pentru toate paginile unui
director prin crearea unui fisier special, numit ".htaccess" in directorul respectiv.
Acest fisier va contine informatii despre tipul autentificarii, drepturi de acces si
fisierul de parole folosit ca si exemplul urmator:
AuthName "pagini_secrete" #informatia realm
AuthType
Basic
# fisierul de parole (de obicei in afara htdocs)
AuthUserFile c:\parole.pw
<LIMIT GET POST>
require valid-user
</LIMIT>
Pentru simplitate, fisierul parole.pw va fi creat in acelasi director ca si pagina cu
ajutorul programului htpasswd instalat odata cu serverul Apache. Intr-un caz
real, fisierul de parole se va crea intr-un director aflat in afara spatiului rezervat
paginilor (in afara directorului htdocs). Fisierul de parole va contine siruri de
genul nume_utilizator:parola_criptata. Spre exemplu pentru nume=gigel si
parola=gigel se creeaza o linie de genul:
gigel:$apr1$aS2.....$K0d7UyUtuGnxxTR9wWsX71
la apelul c:\>"C:\Apache\bin\htpasswd.exe" -c -b parole.pw gigel gigel in
directorul unde este pagina.
Pentru ca o anumita pagina din acel director sa fie protejata, trebuie ca ea sa
ceara autentificarea de un anumit nivel (specificat prin realm) in felul urmator
(secventa apare la inceputul paginii):
<?php
if (!isset($HTTP_SERVER_VARS["PHP_AUTH_USER"])) {
header("WWW-Authenticate: Basic realm=\"pagini_secrete\"");
header('HTTP/1.0 401 Unauthorized');
echo 'Nu aveti drepturi de access!';
exit;
}
else {
echo "<p>Buna {$HTTP_SERVER_VARS['PHP_AUTH_USER']}.</p>";
echo "<p>Parola introdusa: {$HTTP_SERVER_VARS
['PHP_AUTH_PW']} .</p>";
}
echo "<P>Autentificare realizata. Puteti vedea informatia din pagina!";
?>
O data introdusa o parola, ea va ramane activa pana la inchiderea navigatorului
pentru toate paginile din director care solicita autentificare cu acelasi realm.
ABD
de inconveniente cum ar fi:
l
l
l
Activitate
2
144
<?php
$user = $HTTP_POST_VARS["user"];
$parola = $HTTP_POST_VARS["parola"];
if ( $user != "gigel" || $parola != "gigel" ) {
?>
<FORM action="a5232.php" method="POST">
<TABLE>
<TR><TD><CENTER>Utilizator:
<INPUT type="TEXT" name="user">
</CENTER></TD></TR>
<TR><TD><CENTER>Parola:
<INPUT type="PASSWORD" name="parola">
</CENTER></TD></TR>
<TR><TD><CENTER>
<INPUT type="SUBMIT" value="Log-in">
</CENTER></TD></TR>
</TABLE>
</FORM>
<?php
}
else {
echo "Acestea sunt informatii doar pentru Gigel!";
}
?>
ABD
Copiati fisierul in directorul htdocs al serverului de Web. Incarcati
in navigator adresa http://localhost/a5232.php si verificati
autentificarea.
145
ABD
</TABLE>
</FORM>
</BODY> </HTML>
<!-- pagina inreg.php -->
<?php
$user = trim($HTTP_POST_VARS["user"]);
$parola = trim($HTTP_POST_VARS["parola"]);
$email = trim($HTTP_POST_VARS["email"]);
$telefon = trim($HTTP_POST_VARS["telefon"]);
// verificare corectitudine date de intrare
if ( empty($user) || empty($parola) || empty($email)) {
echo "Nu a-ti introdus toate datele!<BR>";
die ('<A HREF="inreg.html">Modifica</A>');
}
// conectare la baza de date
@ $bd = mysql_connect ("localhost", "portar", "control!");
if( !$bd )
die ("Baza de utilizatori nedisponibila! Reveniti.");
mysql_select_db ("Aplicatia");
// verificare unicitate utilizator
$verific = "SELECT * FROM Utilizatori WHERE user = \"$user\"";
$res = mysql_query ($verific);
if (mysql_num_rows($res) > 0) {
echo "Mai exista un utilizator '$user' !<BR>";
mysql_close($bd);
die ('<A HREF="inreg.html">Modifica</A>');
}
// adaugare utilizator nou in baza de date
$adaug = "INSERT INTO Utilizatori (user, parola, email, telefon) VALUES ";
$adaug .= "('$user', '$parola', '$email', '$telefon')";
$res = mysql_query ($adaug);
if ($res) {
echo 'Felicitari. Inregistrare efectuata cu succes!<BR>';
echo '<A HREF="login.html">pagina de log-in</A>';
}
else
echo 'Inregistrarea nu s-a putut efectua. Reveniti!';
mysql_close ($bd);
?>
Pagina de log-in va tine cont de inregistrarile din tabela Utilizatori pentru
autentificare.
<!-- pagina login.html -->
<HTML><HEAD><TITLE>Autentificare</TITLE></HEAD>
<BODY>
<H1>Introduceti numele si parola </H1>
<P><HR><P>
<FORM action="login.php" method="POST">
146
ABD
<TABLE>
<TR><TD>Utilizator:</TD>
<TD> <INPUT type="TEXT" name="user">
</TD></TR>
<TR><TD>Parola: </TD>
<TD> <INPUT type="PASSWORD" name="parola">
</TD></TR>
<TR><TD> <INPUT type="SUBMIT" value="Login"></TD>
<TD> <INPUT type="RESET" value="Reset">
</TD></TR>
</TABLE>
</FORM>
</BODY> </HTML>
<!-- pagina login.php. Din cauza setcookie acest comentariu nu va fi copiat in
fisier -->
<?php
$user = trim($HTTP_POST_VARS["user"]);
$parola = trim($HTTP_POST_VARS["parola"]);
// verificare corectitudine date de intrare
if ( empty($user) || empty($parola) ) {
echo "Nu a-ti introdus toate datele!<BR>";
die ('<A HREF="login.html">Incearca din nou</A>');
}
// conectare la baza de date
@ $bd = mysql_connect ("localhost", "portar", "control!");
if( !$bd )
die ("Baza de utilizatori indisponibila! Reveniti.");
mysql_select_db ("Aplicatia");
// autentificare utilizator
$verific = "SELECT * FROM Utilizatori WHERE user = \"$user\"";
$res = mysql_query ($verific);
if (!$res || mysql_num_rows($res) == 0) {
echo "Acces neautorizat!<BR>";
mysql_close($bd);
die ('<A HREF="login.html">Incearca din nou</A>');
}
$inreg = mysql_fetch_object ($res);
$parola_buna= $inreg ->parola;
$email = $inreg ->email;
if ( $parola_buna !=$parola ) {
echo "Acces neautorizat!<BR>";
mysql_close($bd);
die ('<A HREF="login.html">Incearca din nou</A>');
}
// setare informatii cookie pentru utilizatorul conectat
// autentificarea va expira automat dupa 30 min.
$expira= time () + 30*60; // expirare login in 30 min.
header ("Location: main.php");
setcookie("user", $user, $expira);
147
ABD
setcookie("parola", $parola, $expira);
setcookie("email", $email, $expira);
echo "Autentificare cu succes!";
mysql_close ($bd);
?>
<!-- pagina principala main.php -->
<?php
$user = $HTTP_COOKIE_VARS["user"];
$parola = $HTTP_COOKIE_VARS["parola"];
$email = $HTTP_COOKIE_VARS["email"];
// verificare autentificare
if ( empty($user) || empty($parola) ) {
echo "Utilizator necunoscut!<BR>";
die ('<A HREF="login.html">Incearca din nou</A>');
}
echo "<H1> Pagina principala a Aplicatiei!</H1>";
echo "<P><HR><P>";
echo "Buna ziua $user!";
echo "<P>Adresa ta de e-mail: <A HREF=\"mailto:$email\">$email</A>";
?>
Pe baza acestui schelet simplu de aplicatie se pot dezvolta site-uri mult mai
complexe. In situatii reale trebuie in schimb tinut cont de anumite modificari,
printre care:
l
l
ABD
implementat autentificarea si observatiile referitoare la problemele intampinate.
Fisierul SQL continand comenzile pentru crearea tabelei de utilizatori si fisierele
PHP si HTML vor fi comprimate si transmise prin e - mail la adresa dan@cs.upt.ro.
<< Cuprins
'2010 conf. ing. Dan Pescaru
149
ABD
150