Sunteți pe pagina 1din 150

Administrare Baze de Date Web

2010 - Conf.dr.ing. Dan Pescaru

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

14. PHP - Structuri conditionale si repetitive


a. Instructiuni conditionale
b. Instructiunea if
c. Instructiunea switch
d. Instructiuni repetitive
e. Instructiunea while
f. Instructiunea do while
g. Instructiunea for
h. Tablouri PHP. Instructiunea foreach
i. Instructiuni de control pentru repetitii
15. PHP - Functii. Formulare. Sesiuni.
a. Functii
b. Functii de biblioteca
c. Functii utilizator
d. Transmiterea parametrilor
e. Functii recursive
f. Reutilizarea codului
g. Instructiunea require
h. Instructiunea include
i. Cotrolul sesiunilor
j. Utilizare formulare si sesiuni pentru controlul utilizatorilor
16. Functii. Utilizare fisiere
a. Functii de prelucrare tablouri
b. Functii de prelucrare date calendaristice
c. Functii matematice
d. Functii de prelucrare siruri de caractere
e. Utilizare fisiere
f. Deschiderea si inchiderea unui fisier
g. Scrierea intr-un fisier
h. Citirea dintr-un fisier
i. Functii speciale pentru fisiere
17. Utilizare MySQL in PHP.
a. Limbajul SQL
b. Baze de date. Tabele
c. Utilizatori si privilegii
d. Adaugarea, modificarea si stergerea datelor
e. Interogari SELECT
f. Utilizarea unei baze de date mySQL in PHP
g. Conectarea la server
h. Adaugarea de informatii
i. Cautarea si afisarea rezultatelor
18. Aplicatii Multimedia e-Comerce Complexe
a. Tipuri de aplicatii e-Comerce
b. Brosuri de prezentare
c. Comenzi prin Internet pentru marfuri si servicii
d. Comert cu servicii si bunuri digitale

e. Aplicatii de tip "valoare adaugata"


f. Riscuri si probleme legate de aplicatiile e-comerce
19. Probleme de securitate
a. Utilizare cookies
b. Restrictii legate de cookies
c. Utilizare cookies in PHP
d. Probleme la folosirea cookies
e. Probleme de securitate la site-urile PHP
f. Securitatea serverului de Web
g. Securitatea instalarii PHP
h. Gestiunea utilizatorilor in PHP
i. Autentificarea utilizand serverul de Web
j. Autentificarea folosind PHP

ABD

Cap1. mySQL - Introducere


1. Introducere
1.1. Ce este mySQL?
1.2. Argumente in favoarea mySQL
2. Instalare
2.1. Instalare sub Windows
2.2. Rulare sub Windows
2.3. Instalare sub Linux
2.4. Testarea instalarii

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.

1.2. Argumente in favoarea mySQL


l

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

Poate folosi mai multe procesoare daca sistemul este multi-procesor.


Suport pentru multe limbaje de programare.
Interfete pentru clienti: C, C++, Eiffel, Java, Perl, PHP, Python.
Multiplatforma.
Sunt suportate urmatoarele sisteme de operare: Linux, Win95, Win98, WinNT,
Win2000, AIX, DEC Unix, HP-UX, Mac OS XServer, OS2 Warp, Solaris, SCO
UnixWare etc.
Securitate ridicata.
Utilizeaza parole criptate.
Scalabilitate buna.
Suporta baze de date de mari dimensiuni. Exista aplicatii cu aproximativ 5 miliarde
inregistrari ruland pe MySQL.

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.

2.2. Rulare sub Windows


In Winodws 95/98 se va lansa unul din serverele:
l
l

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:
6

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

2.3. Instalare sub Linux


Pentru instalare se vor urma pasii:
1. Download fisier mysql-3.23.xx.tar.gz 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. Fisierul se va depune intr-un director temporar, de exemplu /tmp/kitmysql.
2. Dezarhivare fisier mysql-3.23.xx-win.tar.gz prin utilizarea comenzii:
gunzip -c mysql-3.23.xx.tar.gz | tar xvf La extragere se va crea automat subdirectorul mysql-3.23.xx.
3. Intrare in subdirector:
cd mysql-3.23.xx
4. Configurare instalare in directorul /usr/local/mysql prin:
./configure --prefix=/usr/local/mysql
5. Compilare executabil:
make
6. Instalare server:
make install
7

ABD
7. Crearea tabelelor implicite:
scripts/mysql_install_db

2.4. Testarea instalarii


Pentru a testa serverul se vor executa urmatoarele comenzi:
l

c:\mysql\bin\mysqlshow

care va produce ca rezultat afisarea bazelor de date disponibile pe server:


Databases
mysql
test
Dupa cum se observa, la instalare sunt create automat doua baze de date: mysql pentru
stocarea utilizatorilor si drepturilor de acces, respectiv test pentru a testa corectitudinea
configuratiei curente.
l

c:\mysql\bin\mysqlshow -u root mysql

care va produce ca rezultat afisarea tabelelor existente in baza de date mysql:


Database: mysql
Tables
columns_priv
db
host
tables_priv
user
l

c:\mysql\bin\mysqladmin -u root shutdown

sau, sub NT,


l

NET STOP mysql

care va opri serverul.


'2010 conf. dr. ing. Dan Pescaru

ABD

Cap.2. Algebra relationala. Proiectarea si


normalizarea unei baze de date.
1. Elemente de algebra relationala
1.1. Introducere
1.2. Definitii
2. Normalizarea unei baze de date relationale
2.1. Proiectarea unei baze de date relationale
2.2. Dependente functionale
2.3. Forme normale
3. Proiectarea unei baze de date
3.1. Crearea unui dictionar de date

1. Elemente de algebra relationala


1.1. Introducere
Principiile algebrei relationale au fost stabilite de F. C. Codd n 1970. Ea
reprezinta fundamentarea matematica a bazelor de date relationale.
n conceptia relationala o baza de date este formata dintr-o colectie de relatii
(tabele, fisiere de date) asupra carora se aplica o colectie de operatori pentru a
gestiona datele continute de relatii.
Un operator relational se aplica asupra unor tabele si va avea ca si rezultat tot o
tabela. Potrivit algebrei relationale nu este permis accesul direct asupra
nregistrarilor dintr-o tabela.
1.2. Definitii
n continuare se vor da cteva definitii a termenilor folositi de algebra relationala.
Constituantii (cmpuri, atribute, caracteristici) sunt informatiile elementare
(atomice) ale unei relatii.
Domeniul unui constituant (tipul) este ansamblul valorilor pe care l poate lua
un constituant. Domeniul este un set de valori atomice.

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

N-upletii din relatie nu sunt ordonati.


Ordinea valorilor n N-upleti este data de ordinea definirii atributelor n
modelul relatiei.
Valorile atributelor din N-upleti sunt atomice. Un atribut nu poate avea valori
multiple. Sunt permise n schimb valori nule.
O relatie poate fi privita ca o specificare a unui tip compus. Definitia tipului
este data de structura relatiei.

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.

2. Normalizarea unei baze de date relationale


10

ABD

2.1. Proiectarea unei baze de date relationale


Normalizarea unei baze de date consta n principal n descompunerea modelului
bazei de date n mai multe relatii astfel nct sa se reduca la maxim redundanta
datelor si implicit sa elimine anomaliile de actualizare. Operatia de normalizare se
bazeaza pe dependentele functionale care exista ntre datele unei aplicatii.
Concret, pasii care trebuie facuti la proiectarea unei baze de date sunt urmatorii:
1. Analiza aplicatiei: analiza circuitului informational, studierea intrarilor si
iesirilor, stabilirea claselor de utilizatori.
2. Analiza semanticii atributelor din entitati: identificarea atributelor si a
sensului lor functional, gruparea atributelor n relatii pe entitati, stabilirea
cheilor primare si externe.
3. Normalizarea relatiilor obtinute la punctul anterior: micsorarea redundantei
prin gruparea atributelor n relatii conform definitiilor pentru formele normale,
stabilirea de constrngeri pentru eliminarea anomaliilor de actualizare.
4. Scoaterea din relatiile principale a atributelor care au peste 70% valori nule.
2.2. Dependente functionale
O dependenta functionala, notata X->Y, ntre doua seturi de atribute a unei
relatii R, specifica o constrngere asupra N-upletilor posibili.
Ea se defineste n felul urmator:
oricare ar fi t1 , t2 in R, t1(X) = t2(X) => t1 (Y) = t 2 (Y)
Se spune n acest caz ca X determina functional pe Y sau ca Y este dependent
functional de X.
Faptul ca X nu determina functional pe Z se va nota X |-> Z.
Pentru determinarea dependentelor functionale se pot aplica urmatoarele reguli
de inferenta (prin XY se noteaza concatenarea seturilor de atribute X si Y):

2.3. Forme normale


Normalizarea bazei de date presupune aducerea relatiilor gradual pe diverse
forme normale. Fiecare forma normala preia constrngerile formei anterioare la
care adauga noi conditii.
Forma normala 1 (1NF) cere:
l

11

domeniul atributelor sa cuprinda valori atomice; se interzic cmpurile

ABD

compuse sau "relatii n relatie"


fiecare atribut din N-uplet trebuie sa aibe o singura valoare n domeniu.

Forma normala 2 (2NF) cere:


l
l

relatia sa fie n 1NF


orice atribut neprim (care nu face parte din cheia primara) din R sa fie
complet dependent functional de cheia primara a relatiei.

O alta varianta: se cere sa nu existe atribute care sa depinda numai de o parte a


cheii primare.
Forma normala 3 (3NF) cere:
l
l

relatia sa fie n 2NF


nu exista nici un atribut neprim care sa fie dependent tranzitiv de cheia
primara a relatiei

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

este complet dependent functional de orice cheie din R


este dependent netranzitiv de orice cheie din R

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

nu determina univoc pe B si C (A |-> B si A |-> C)


conduce la valori multiple a lui B
conduce la valori multiple a lui C
si C sunt independente ntre ele.

Aducerea unei baze de date pe o forma normala superioara presupune


extragerea unor atribute din relatiile existente si crearea pe baza lor a unor noi
relatii astfel nct rezultatul sa respecte forma normala n cauza. Acest lucru duce
la fragmentarea bazei de date dar elimina din anomaliile de actualizare si reduce
spatiul pierdut datorita redundantei datelor.

12

ABD

3. Proiectarea unei baze de date


Proiectarea atenta a bazei de date este o premisa esentiala pentru succesul unei
aplicatii.
Proiectarea va incepe cu analiza problemei si identificarea datelor care intervin.
Aceste date sunt apoi puse impreuna intr-o singura tabela temporara.
Dupa analiza aplicatiei, primul pas consta in normalizarea bazei de date conform
principiilor enuntate anterior. Chiar daca aceasta normalizare este un proces
complex si de durata, el contribuie esential la evitarea problemelor si
complicatiilor ulterioare. Ca si rezultat se vor obtine mai multe tabele in locul
tabelei tempoarare de la analiza. Pentru acestea se vor alege apoi cheile primare.
Dupa efectuarea normalizarii, se vor lua in considerare si alti factori care
influenteaza proiectarea:
l

Considerente de securitate - pot cere scoaterea unor date sensibile din


tabele accesate public, chiar daca normalizarea nu o cerea.
Viteza de cautare a informatiilor - este un factor esential care poate cere
chiar incalcarea unor forme normale, prin repetarea datelor in tabele.
Viteza de adaugare si modificare a datelor - poate cere renuntarea la unii
indecsi sau chiar reorganizarea datelor.

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

Descrierea scopului bazei de date si utilizarii acesteia.


Referiri la aspecte precum: dimensiunea prevazuta a diverselor tabele,
fisiere index necesare etc.
Descrierea detaliata a fiecarei tabele, incluzand toate campurile, tipul
acestora, comentarii privind utilitatea etc.
Codul sursa SQL pentru crearea structurii: bazei de date, tabelelor,
utlizatorilor si drepturilor, indecsilor, vederilor etc. Codul de obicei este sub
forma unuia sau mai multe fisiere text cu extensia SQL.

Descrierea tabelelor se poate face sub urmatoarea forma:


Pesoane
Camp

13

Tip

Constrangeri

Comentarii

BD
buletin

caracter(8)

cheie primara

nume

caracter(24) necesar (not null)

numarul de buletin (cu tot cu serie)


numele de familie

prenume caracter(32) necesar (not null)

prenumele

data_n

data nasterii

data

Indecsi necesari pentru cautari: buletin, nume.


'2010 conf. dr. ing. Dan Pescaru

14

ABD

Cap.3. Conectarea la serverul mySQL


1. Conectarea la serverul mySQL
1.1. Folosirea unui client tip linie de comanda
1.2. Verificarea conectarii si a starii serverului
2. Crearea si utilizarea unei baze de date
2.1. Crearea unei baze de date
2.2 Utilizarea unei baze de date
1. Conectarea la serverul mySQL
1.1. Folosirea unui client tip linie de comanda
Cel mai facil client pentru conectarea la serverul de mySQL este cel tip linie de
comanda care face parte din kit-ul standard de instalare mySQL.
El se numeste mysql.exe si permite conectarea atat local cat si la un server la
distanta.
Sintaxa de apel este:
> mysql -h nume_calculator_server -u nume_utilizator -p
El va fi apelat din subdirectorul bin al directorului de instalare (de obicei
c:\mysql\bin).
Semificatia parametrilor de apel este urmatoarea:
l

-h nume_calculator_server - este numele masinii pe care se gaseste


instalat serverul mysql. Daca conectarea se face local se poate renunta la
optiunea -h sau se poate folosi 'localhost' pentru identificarea masinii.
-u nume_utilizator - este numele utilizatorului (contului) care acceseaza
serverul. El va stabili drepturile de acces la bazele de date de pe server.
Daca conectarea se face local numele poate lipsi (conectare anonima),
conectrea facandu-se implicit cu utilizatorul ODBC (cu drept de
administrator). Din acest motiv trebuie limitat accesul utlizatorilor la masina
pe care este instalat serverul. La conectarea de la distanta numele de
utilizator nu poate fi omis. In general conectarea se face specificand
complet numele utilizatorului si al masinii: root@localhost sau
adi@serverul_meu.domeniu.ro.
-p - forteaza citirea unei parole la conectare. Poate lipsi daca utilizatorul
respectiv nu are stabilita inca o parola sau daca conectarea se face local in
mod anonim. Parola efectiva se va citi dupa executarea comenzii.

Deconectarea clientului se poate face cu comanda QUIT.


Clientul mysql.exe se poate utiliza si pentru a rula un fisier text de comenzi SQL.
Pentru aceasta se va utiliza sintaxa:
15

ABD

> mysql -h nume_calculator_server -u nume_utilizator -p < nume_fisier.sql


Daca fisierul nu se gaseste pe calea curenta, aceasta cale trebuie adaugata
inaintea numelui fisierului.
1.2. Verificarea conectarii si a starii serverului
Pentru verificarea conectarii se poate rula o interogare foarte simpla care va
avea ca rezultat afisarea versiunii programului si a datei curente pe server:
mysql>SELECT VERSION(), CURRENT_DATE;
De retinut!
l

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.

Comanda anterioara este echivalenta cu:


mysql> select
-> Version()
-> ,
-> CURRENT_DATE;
O alta interogare utila este "SHOW". Ea poate fi utilizata pentru obtinerea de
diverse informatii despre server. Spre exemplu, daca se doreste vizualizarea
informatiilor despre bazele de date disponibile se va rula comada:
mysql>SHOW databases;
In aceiasi maniera se pot obtine informatii despre tabelele apartinand unei baze
de date (spre exemplu baza de date 'mysql' creata automat la instalare):
mysql>SHOW tables form mysql;
sau despre coloanele unei tabele:
mysql>SHOW columns from user from mysql;
2. Crearea si utilizarea unei baze de date
2.1. Crearea unei baze de date
Crearea unei baze de date se poate face simplu apeland comanda:
mysql>CREATE DATABASE nume_db;
Crearea unei baze de date corespunde crearii unui director in care vor fi pastrate
elementele specifice cum ar fi: tabele, indecsi, jurnale etc. Daca deja exista o
16

ABD

baza de date cu numele specificat se va da un mesaj de eroare.


Pentru stergerea unei baze de date se poate utiliza sintaxa:
mysql>DROP DATABASE nume_db;
2.2 Utilizarea unei baze de date
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;
Chiar daca o singura baza de date poate fi activa la un moment dat, o interogare
poate referi tabele si din alte baze de date prin utilizarea prefixarii cu numele
bazei de date respective (ex. db2.tabela5).
Exemplu:
mysql>USE mysql;
mysql>SHOW TABLES;
mysql>SELECT * FROM db;
3. Tema 2.2
Creati o baza de date numita BANCA. Cautati directorul creat pe disc care
corespunde bazei de date create.
Rulati comanda:
SHOW DATABASES;
Stergeti baza de date si creati-o din nou.
Selectati aceasta baza de date si rulati comanda:
SHOW TABLES;
Notati calea unde s-a creat directorul si raspunsul la ultima interogare.
'2010 conf. dr. ing. Dan Pescaru

17

ABD

Cap.4. Tipuri de date. Tabele.


1. Tipuri de date
1.1. Tipuri de date numerice
1.2. Tipuri de date data calendaristica si timp
1.3. Tipuri de date sir de caractere
1.4. Tipuri de date binare mari (BLOB)
1.5. Tipuri de date speciale
2. Constante, identificatori, comentarii
2.1. Constante
2.2. Identificatori
2.3. Comentarii
3. Operatori si functii mySQL
3.1. Paranteze de grupare
3.2. Operatori aritmetici
3.3. Operatori logici
3.4. Operatori de comparare
3.5. Functii pe siruri de caractere
3.6. Functii matematice
3.7. Functii de tip data calendaristica si timp
4. Crearea si stergerea tabelelor
1. Tipuri de date
Ca orice limbaj de programare, limbajul SQL suporta anumite tipuri de date. Ele
pot fi in general impartite in: numerice, logice, data calendaristica, timp, siruri de
caractere si date binare mari (BLOB - binary large object).
Din motive de implementare, fiecare sistem de gestiune de baze de date
implementeaza propriile subtipuri ale tipurilor de baza. Aceasta situatie poate
pune uneori probleme de compatibilitate la trecerea bazelor de date de pe un
sistem pe altul.
In continuare se vor prezentat tipurile de date suportarte de mySQL.
Ca si regula generala, notatia:
tip [(M, D)] [optiuni]
are urmatoarea interpretare: tipul de date referit este afisat pe M pozitii, eventual
cu D pozitii in partea zecimala. Toate valorile ce se gasesc in paranteze drepte
semnifica marimi optionale.
Observatie: optiunile M si D nu influenteaza insa spatiul de stocare necesar
pentru memorarea valorilor de acel tip.
Valorile optionale au urmatoarea semnificatie:
l
l

18

UNSIGNED - permite memorarea doar a valorilor pozitive.


ZEROFILL - la afisare, valorile numerice vor fi precedate de '0' pana la

ABD

lungimea de afisare (ex. 0003)


BINARY - specifica faptul ca interpretarea caracterelor se va face in cod
ASCII (la compararea a doua siruri se va face distinctie intre litere
mari/mici).

1.1. Tipuri de date numerice


1. TINYINT [(M)] [UNSIGNED] [ZEROFILL]

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.

1.2. Tipuri de date data calendaristica si timp

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).

1.3. Tipuri de date sir de caractere


1. CHAR (M) [BINARY]

Sir de caractere de lungime fixa. Daca se memoreaza un sir mai scurt el va


fi completat cu spatii la dreapta pana la lungimea M specificata. Lungimea
M a sirului poate lua valori in intervalul [1..255]. Spatiile de la sfarsitul sirului
sunt indepartate automat la interogarea campului. Daca nu se specifica
optiunea BINARY, compararea valorilor se face fara a tine cont de felul
literelor (mari/mici).
2. BIT
BOOL
CHAR
Sunt sinonime cu declaratia CHAR(1).
3. VARCHAR (M) [BINARY]
Sir de caractere de lungime variabila. La memorare, spatiile de la sfarsitul
sirului sunt indepartate. Lungimea M a sirului poate lua valori in intervalul

20

ABD

[1..255]. Daca nu se specifica optiunea BINARY, compararea valorilor se


face fara a tine cont de felul literelor (mari/mici).

1.4. Tipuri de date binare mari (BLOB)


Se folosesc pentru a retine obiecte binare (BLOB) de mari dimensiuni (ex.
imagini, secvente audio sau video) sau pentru a retine texte de dimensiune in
general mai mare de 255 caractere (TEXT). La comparatia campurilor tip TEXT
nu se va tine cont de tipul caracterelor (mari/mici).
1. TINYBLOB

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.

1.5. Tipuri de date speciale


1. ENUM ('value1','value2',...)

Enumerare de elemente tip sir de caracter. Un obiect de acest tip poate


avea la un moment dat o singura valoare dintre cele enumerate sau
valoarea NULL. Valoarea " " (sir vid) este considerata valoare de eroare. Un
tip enumerare poate defini maxim 65535 de valori distincte.
2. SET ('value1','value2',...)
Multime de elemente tip sir de caracter. Un obiect de acest tip poate contine
la un moment dat mai multe valori distincte dintre cele definite sau poate fi
gol (nu contine nici o valoare). Un tip multime poate defini maxim 65 de
valori membru.

2. Constante, identificatori, comentarii


2.1. Constante
l

21

Constantele tip sir de caractere se includ intre apostroafe sau ghilimele:

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

mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello' ;


mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello" ;

Constantele intregi sunt reprezentate printr-un sir de cifre zecimale.


Constantele reale contin semnul '.' pentru specificarea partii zecimale.
Ambele tipuri pot fi precedate de semnul '-' pentru a indica numere negative.
Ex:
13534
342.3453
Constanta NULL este folosita cu semnificatia "nici o valoare". Se face
diferenta intre NULL si numarul 0 sau sirul vid "".

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

Lungime maxima Caractere interzise


64
'/'
64
'/' si '.'
64
255

Referirea la o coloana in cadrul unei interogari se poate face in mai multe


moduri, functie de contextul existent:
Referinta la coloana

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

Comentarii pe o singura linie care incep cu # si continua pana la sfarsitul


liniei;
Comentarii pe o singura linie care incep cu -- si continua pana la sfarsitul
liniei. Este necesar cel putin un spatiu dupa semnul --;
Comentarii pe mai multe linii care incep cu /* si se incheie cu */ ;
Rulati secventele:
mysql> SELECT 1+1; # Acest comentariu continua pana la sfarsitul liniei
mysql> SELECT 1+1; -- Acest comentariu continua pana la sfarsitul liniei

Activitate 2

mysql> SELECT 1 /* Acesta este un comentariu imbricat */ + 1;


mysql> SELECT 1+
> /*
> Acesta este
> un comentariu multi-linie
> */
> 1;

3. Operatori si functii mySQL


3.1. Paranteze de grupare
Sunt folosite pentru a schimba ordinea de evaluare in interiorul expresiilor.
Parantezele folosite sunt doar paranteze rotunde.
Rulati secventele:
Activitate 3
mysql> SELECT 1+2*3;
23

ABD
mysql> SELECT (1+2)*3;

3.2. Operatori aritmetici


Operatorii aritmetici opereaza asupra numerelor intregi cu precizia BIGINT (pe
64 biti). Sunt disponibili urmatorii operatori:
l
l
l
l

+ 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);

3.3. Operatori logici


Operatorii logici intorc 1 pentru adevarat si 0 pentru fals.
l

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

mysql> SELECT NOT 1, NOT NULL, ! (1+1), ! 1+1 ;


mysql> SELECT 1 OR 0, 0 OR (1-1), 1 || NULL ;
mysql> SELECT 1 && NULL, 1 && 0, 1 AND (0+1) ;

3.4. Operatori de comparare


Operatorii de comparare returneaza 1 pentru adevarat, 0 pentru fals si NULL
daca nu se poate efectua comparatia.
Ei pot compara atat numere cat si siruri de caractere. La compararea unui numar
cu un sir se incearca transformarea sirului in numarul pe care il contine.
La compararea a doua siruri nu se va tine cont de litere mari/mici.

24

ABD
l
l
l
l
l
l
l

l
l
l
l

= egalitate; la compararea cu NULL intoarce NULL;


<> sau != inegalitate;
< - mai mic;
<= - mai mic sau egal;
> - mai mare;
>= - mai mare sau egal;
<=> - echivalenta; la compararea cu NULL intoarce 0 sau 1 (1 doar la NULL
<= > NULL); daca ambii operanzi sunt diferiti de NULLse comporta ca si =;
IS NULL - testeaza daca operandul are valoarea NULL;
IS NOT NULL - testeaza daca operandul este diferit de NULL;
ISNULL(expr) - testeaza daca expresia are valoarea NULL;
expr BETWEEN min AND max - testeaza daca valoarea expresiei este in
intervalul [min..max];
expr IN (value,...) - testeaza daca valoarea expresiei este in lista de valori
specificata;
expr NOT IN (value,...) - testeaza daca valoarea expresiei nu este in lista de
valori specificata;
IF(expr1,expr2,expr3) - testeaza valoarea de adevar a expr1 (falsa daca
este 0 sau NULL) si intoarce expr2 pentru adevarat respectiv expr3 pentru
fals;
Rulati secventele:

Activitate 6

mysql> SELECT 1 = 0, '0.0' = 0, '.01' = 0.01 ;


mysql> SELECT .01 <> '0.01', 'abc' <> 'abcd' , 'abc' <> 'ABC' ;
mysql> SELECT 0.1 <= 2, 2 >= 2, 5 > '3' ;
mysql> SELECT 0 <=> NULL, NULL = NULL, NULL < = > NULL ;
mysql> SELECT 0 IS NULL, NULL IS NULL, 0 IS NOT NULL ;
mysql> SELECT 1 BETWEEN 2 AND 3, 'b' BETWEEN 'a' AND 'c', 2
BETWEEN 2 AND '3' ;
mysql> SELECT 2 IN (0,3,5,'abc') , 'abc' IN (0,3,5,'Abc') ;
mysql> SELECT IF(1&gt2,2,3), IF(1&lt2,'da','nu') ;

3.5. Functii pe siruri de caractere


Functiile pe siruri considera implicit primul caracter pe pozitia 1.
l

25

ASCII(str) - intoarce codul ASCII al caracterului de pe pozitia 1 din sir. Daca


sirul este vid intoarce 0.
CONV(N, from_base, to_base) - converteste numarul N considerat in baza
from_base in valoarea sa in baza to_base.
CHAR(N,...) - converteste sirul de numere primite intr-un sir de caractere ale
caror coduri ASCII sunt egale cu cele din sirul initial.
CONCAT(str1,str2,...) - concateneaza sirurile primite ca argument,
returnand sirul rezultat.
LENGTH(str) - intoarce lungimea (numarul de caractere) a sirului primit ca
si argument.
LOCATE(substr,str)
POSITION(substr IN str) - cauta prima aparitie a sirului substr in sirul str.

ABD

l
l

l
l

Daca il gaseste returneaza pozitia, daca nu, returneaza 0.


LEFT(str,len) - intoarce un sir format din primele len caractere din sirul dat.
RIGHT(str,len) - intoarce un sir format din ultimele len caractere din sirul
dat.
SUBSTRING(str,pos,len)
MID(str,pos,len) - intorc subsirul de pe pozitia pos, de lungime len caractere
din sirul str.
SUBSTRING_INDEX(str,delim,count) - intoarce subsirul pana la count
aparitii ale caracterului delimitator delim. Daca delim este pozitiv intoarce
prima parte a sirului, daca este negativ, ultima parte.
LTRIM(str)
RTRIM(str)
TRIM(str) - intoarce sirul str fara spatiile de la inceput (LTRIM), sfarsit
(RTRIM) sau din ambele parti (TRIM).
SPACE(N) - intoarce un sir format din N spatii.
LOWER(str)
UPPER(str) - intorc sirul str cu toate caracterele convertite la litere mici,
respectiv litere mari.
sir (NOT) LIKE tipar - compara sirul sir cu tiparul dat. Intoarce adevarat (1)
daca se potrivesc. Tiparele pot include caracterele speciale: '_' care se
potriveste cu orice caracter si '%' care poate inlocui orice secventa de 0 sau
mai multe caractere. Ex. 'ana' LIKE 'an_', 'ana' LIKE 'a%', 'ana' NOT LIKE
'a%z'.
Rulati secventele:

Activitate 7

mysql> SELECT ASCII('0'), CONV("125",10,2), CHAR(77,121) ;


mysql> SELECT CONCAT('My', 'S', 'QL'), LENGTH('text'), LOCATE
('me', 'Ana are MERE') ;
mysql> SELECT LEFT('MySQL', 2), RIGHT('MySQL', 3), SUBSTRING
('Pasaport',4,5) ;
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2), CONCAT
('A', LTRIM(' na ')) ;
mysql> SELECT CONCAT('a',SPACE(6),'b'), LOWER('Ana are MERE'),
UPPER('Ana are MERE') ;
mysql> SELECT 'ana' LIKE 'An_', 'ana' LIKE 'a%', 'ana' LIKE 'a%z' ;

3.6. Functii matematice


Toate functiile matematice intorc NULL in caz de eroare.
l
l

26

ABS(X) - valoarea absoluta (fara semn) a lui x.


SIGN(X) - testeaza semnul lui x, intoarce -1 pentru x negativ, 1 pentru x
pozitiv si 0 in caz contrar
MOD(N,M)
% - modulo (restul impartirii) lui N la M.
FLOOR(X) - cea mai mare valoare intreaga mai mica decat x (rotunjire in
jos)
CEILING(X) - cea mai mica valoare intreaga mai mare decat x (rotunjire in

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

mysql> SELECT ABS(-32), SIGN(-32), MOD(29,10) ;


mysql> SELECT FLOOR(1.23), CEILING(1.23), ROUND(1.58) ;
mysql> SELECT EXP(3), LOG(3), LOG10(100) ;
mysql> SELECT POW(2,5), SQRT(16), PI() ;
mysql> SELECT COS(PI()), RAND(20), RAND(20), RAND() ;
mysql> SELECT LEAST(2,0), LEAST("B","A","C"), GREATEST(2,0) ;

3.7. Functii de tip data calendaristica si timp


l

l
l
l
l
l
l
l
l
l
l

DAYOFWEEK(date) - indexul zilei din spatamana al datei specificate


(1=duminica, 2=luni etc.)
DAYOFYEAR(date) - numarul zilei din an pentru data specificata
DAYNAME(date) - numele (in engleza) al zilei din data specificata
MONTHNAME(date) - numele (in engleza) al lunii din data specificata
YEAR(date) - extrage anul din data specificata
HOUR(time) - extrage ora din timpul precizat
MINUTE(time) - extrage minutul din timpul precizat
SECOND(time) - extrage secunda din timpul precizat
CURDATE() - intoarce data curenta in format 'YYYY-MM-DD'
CURTIME() - intoarce ora curenta in format 'HH:MM:SS'
NOW()
SYSDATE() - intoarce data si ora curenta in format 'YYYY-MM-DD
HH:MM:SS'
SEC_TO_TIME(seconds) - intoarce timpul in format 'HH:MM:SS'
reprezentat de numarul de secunde specificate
TIME_TO_SEC(time) -converteste timpul specificat in numar de secunde
scurse de la ora 00:00:00
Rulati secventele:

27

ABD

Activitate 9

mysql> SELECT NOW(), DAYOFWEEK(NOW()), DAYOFYEAR(NOW


()) ;
mysql> SELECT DAYNAME(NOW()), MONTHNAME(NOW()), YEAR
(NOW()) ;
mysql> SELECT CURTIME(), HOUR(CURTIME()), MINUTE(CURTIME
()) ;
mysql> SELECT SEC_TO_TIME(66), TIME_TO_SEC("00:01:06") ;

3.8. Functii speciale


l
l
l
l

DATABASE() - numele bazei de date active


USER() - numele utilizatorului coectat la server
VERSION() - returneaza versiunea serverului MySQL instalat
PASSWORD(str) - criptare sir dupa metoda interna prin care MySQL isi
pastreaza parolele; criptarea nu este reversibila (nu se poate calcula sirul
de plecare pornind de la cheia criptata)
FORMAT(N,D) - returneaza numarul N in format '#,###,###.##' cu D
zecimale
Rulati secventele:

Activitate 10

mysql> SELECT DATABASE(), USER(), VERSION() ;


mysql> SELECT FORMAT(345674355.35,3), PASSWORD("parola") ;

4. Crearea si stergerea tabelelor


Datele rezultate din procesul de analiza a problemei ce trebuie implementata se
impart in tabele prin procesul de normalizare. In acest fel o baza de date va fi
formata dintr-o colectie de tabele. Pentru a crea o tabela se va utiliza comanda
SQL CREATE TABLE.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
l

28

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.
IF NOT EXISTS - inhiba mesajul de eroare care se genereaza daca la
incercarea de a crea o tabela care mai exista.
create_definition - pentru definirea coloanelor este un sir de tipul:
col_name type [NOT NULL | NULL] [DEFAULT default_value]
[AUTO_INCREMENT] [PRIMARY KEY]
col_name - nume coloana
type - tip coloana (vezi sectiunea 1)
NOT NULL - nu se permit valori NULL in acest camp (campul trebuie
completat in orice situatie)
NULL - permite valori NULL in camp (optiune implicita daca nu se
specifica nimic)

ABD

DEFAULT default_value - completeaza campul lasat liber cu valoarea


implicita default_value
AUTO_INCREMENT - daca nu se insereaza nimic in camp, se va
genera automat o valoare mai mare cu o unitate fata de cea mai mare
valoare din acel camp. Poate fi specificata o singura coloana cu acest
parametru intr-o tabela. Coloanele specificate astfel trebuie indexate.
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 ...)".
create_definition - pentru definirea indexilor are forma:
INDEX (coloana1,...)

Pentru a sterge o tabela se va folosi comanda:


DROP TABLE [IF EXISTS] tbl_name
Parametrul IF EXISTS va inhiba mesajul de eroare care apare daca tabela nu
exista.

Selectati cu ajutorul comenzii USE baza de date BANCA creata la Tema 2.2.
Creati o tabela Deponent ruland comanda:

Activitate 11

mysql> CREATE TABLE Deponent (


mysql> nr_buletin char(8) NOT NULL PRIMARY KEY,
mysql> cnp char(13) NOT NULL,
mysql> nume char(24) NOT NULL,
mysql> prenume char(24) NOT NULL,
mysql> datan date,
mysql> oras char(24) DEFAULT 'Timisoara',
mysql> adresa char(32),
mysql> telefon char(9),
mysql> index (cnp), index (nume)
mysql> );
Verificati corectitudinea tabelei create cu ajutorul comenzilor:
mysql> SHOW COLUMNS FROM Deponent ;
mysql> SHOW INDEX FROM Deponent ;

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

Cap.5. Gestiunea Accesului


1. Sistemul de privilegii al MySQL
1.1. Introducere
1.2. Utilizatori si parole MySQL
1.3. Principiul "minimului de privilegii necesare"
1.4. Privilegiile puse la dispizitie de MySQL
2. Crearea utilizatorilor si stabilirea privilegiilor
2.1. Comanda GRANT
2.2. Vizualizarea privilegiilor
2.3. Conectarea la server folosind parola
3. Retragerea privilegiilor
1. Sistemul de privilegii al MySQL
1.1. Introducere
Functia pricipala a sistemul de privilegii al MySQL este aceea de a autentifica si
autoriza utilizatorii conectati la server. Autorizarea se refera la permisiunea de a
rula interogari precum SELECT, INSERT, UPDATE sau DELETE.
O clasa aparte de privilegii se refera la drepturile de administrare si de
interactinoare cu sistemul de operare.
Termenul privilegiu denota in general un drept al unui utilizator de a actiona intrun anumit fel asupra unui obiect al bazei de date (tabela, camp, index etc.).
1.2. Utilizatori si parole MySQL
Exista diferente semnificative intre sistemul de utilizatori si parole MySQL si
sistemul Unix-ului sau Windows-ului:

Numele de utilizatori MySQL pot avea 16 caractere semnificative pe cand in


majoritatea implementarilor UNIX aceasta valoare este de 8 caractere.
Numele utilizatorilor si parolele sunt pastrate separat de mySQL si nu au
nimic in comun cu cele din sistemul de operare.
MySQL cripteaza parolele folosind un algoritm diferit de cel utilizat de UNIX
sau Windows. Algoritmul de criptare este ireversibil.

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

1.3. Principiul "minimului de privilegii necesare"


Principiul "minimului de privilegii necesare" poate fi folosit pentru a spori
securitatea oricarui calculator, nu doar a serverului MySQL. El este foarte simplu,
dar este in acelasi timp foarte important sa se tina seama de el:
Un utilizator (sau proces) trebuie sa aiba cel mai scazut nivel de privilegii,
suficient pentru a putea executa sarcinile care i-au fost alocate.
1.4. Privilegiile puse la dispizitie de MySQL
Informatiile despre privilegii sunt stocate in tabelele user, db, host, tables_prv
si columns_priv din baza de date mysql. Serverul va citi continutul acestor
tabele ori de cate ori sistemul de privilegii trebuie sa actioneze.
Tabelul urmator prezinta sistemul de privilegii impreuna cu numele coloanelor din
tabelele de privilegii:
Denumire
coloana
select Select_priv
insert Insert_priv
update Update_priv
delete Delete_priv
index Index_priv

Privilegiu

Context
tabele
tabele
tabele
tabele
tabele

alter

Alter_priv

tabele

create

Create_priv

drop

Drop_priv

baza de date, tabele sau


indecsi
baza de date, tabele

grant

Grant_priv

baza de date, tabele

shutdown Shutdown_priv

administrare server

process Process_priv

administrare server

file

File_priv

acces la fisiere externe

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

Cateva dintre aceste privilegii necesita o atentie aparte:

32

Privilegiul grant permite utilizatorilor sa dea mai departe privilegiile lor si


altor utilizatori. In acest fel, doi utilizatori cu privilegii diferite si le pot
combina.
Privilegiul alter poate fi folosit pentru a redenumi tabele, modificand astfel

ABD

l
l
l

baza de date si facand astfel inutilizabile programele altor utilizatori.


Privilegiul file poate fi folosit pentru a citi informatii sensibile de pe server.
Privilegiul shutdown da posibilitate opririi serverului de la distanta.
Privilegiul process poate fi utilizat pentru a vedea continutul interogarilor ce
se executa in acel moment, inclusiv cele de setare a parolei. De asemenea
el da posibilitatea opririi fortate a conexiunilor altor utilizatori.

Exista si lucruri care nu sunt acoperite se sistemul de privilegii al mySQL, printre


care:

Nu se poate specifica explicit ca unui utilizator i se refuza dreptul de a se


conecta.
Nu se poate da dreptul unui utilizator pentru a crea si sterge tabele intr-o
baza de date, dar nu poate sterge si baza de date.

2. Crearea utilizatorilor si stabilirea privilegiilor


2.1. Comanda GRANT
Comanda GRANT permite crearea utilizatorilor si/sau stabilirea, respectiv
modificarea privilegiilor acestora pe patru nivele de privilegii:

l
l
l
l

Global - se aplica tuturor bazelor de date existente pe un server


Database - se aplica tuturor tabelelor dintr-o baza de date
Table - se aplica tuturor coloanelor dintr-o tabela
Column - se aplica doar coloanelor specificate explicit

Forma generala a comenzii GRANT este:


GRANTprivilegii [coloane]
ONcomponenta
TOnume_utilizator [IDENTIFIED BY 'parola']
[WITH GRANT OPTINS]
Semnificatia clauzelor (clauzele din paranteze drepte sunt optionale) este
urmatoarea:

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

privilegiilor la nivel de coloane.


componenta - este numele unei baze de date sau tabele asupra carora vor
fi stabilite privilegiile. Toate bazele de date se pot specifica prin *.*. Acest
nivel se numeste nivel Global de privilegii. Semnul *.* se poate inlocui si cu
*, dar in acest caz nu trebuie sa existe nici o baza de date selectata, in caz
contrar privilegiile se aplica doar asupra bazei de date respective. Nivelul
Database se poate specifica prin nume_bd.*, iar nivelul Table prin
nume_bd.nume_tabela. Daca se specifica doar nume_tabela se va
interpreta ca fiind o tabela a bazei de date selectate. Nivelul Column se va
obtine prin folosirea unei liste de coloane (vezi optiunea precedenta) nevide.
nume_utilizator - este numele utilizatorului (contul) caruia i se atribuie
privilegiile. El poate contine si un nume de statie de pe care are dreptul sa
se conecteze. Astfel, utilizatorul "gigel" va fi interpretat ca
"gigel@localhost" si va fi diferit de " gigel@ceva.com". Acest lucru este util
pentru ca pot exista in realitate utilizatori diferiti cu nume identice dar care
lucreaza pe statii diferite. Tot de aici se poate restrictiona accesul doar de la
anumite statii. Un grup de statii se pot specifica printr-un domeniu generic.
Spre exemplu "gigel@'%.ro'" inseamna ca utilizatorul "gigel" se poate
conecta de la orice statie din domeniul ".ro". Numele simplu "gigel" este
echivalent cu "gige@'%'" si permite conectarea de la orice statie.
parola - specifica parola cu care utilizatorul se va conecta. Parola trebuie in
general sa nu fie usor de ghicit (sa nu fie chiar numele contului sau un
cuvant din dictionar). Daca optiunea IDENTIFIED BY lispseste, utilizatorul
se va putea conecta fara parola, ceea ce reprezinta o grava lacuna de
securitate.
WITH GRANT OPTION - da dreptul utilizatorului sa dea privilegii
echivalente cu ale sale altor utilizatori. Acesta optiune poate fi utilizata
pentru a delega dreptul de administrare, inclusiv creare de utilizatori, unor
administratori ale unor baze de date particulare de pe server. Acesti
administratori nu vor putea insa sa interactioneze cu alte baze de date.

Dupa crearea unui utilizator, parola sa se poate schimba prin comanda:


mysql> SET PASSWORD FOR utilizator = PASSWORD("noua_parola");

2.2. Vizualizarea privilegiilor


Vizualizarea privilegiilor unui utilizator se poate face prin comanda:
mysql> SHOW GRANTS FOR utilizator;
2.3. Conectarea la server folosind parola
Conectarea la server se poate face local sau de la distanta folosind diversi clienti
mySQL. Toti acesti clienti vor permite trimiterea spre server a informatiilor legate
de numele utilizatorului si parola.
Clientul standard din chitul de distributie se va folosi astfel:
34

ABD

mysql -h nume_server -u nume_utilizator-p


Dupa lansarea comenzii clientul va cere parola de conectare:
Enter password: *****

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

Cap.6. Gestionarea datelor.


1. Inserarea datelor in tabele
1.1. Comanda INSERT
1.2. Utilizare comenzii INSERT
2. Modificarea datelor din tabele
2.1. Comanda UPDATE
2.2. Utilizarea comenzii UPDATE
3. Stergerea datelor din tabele
3.1. Comanda DELETE
3.2. Utilizarea comenzii DELETE
1. Inserarea datelor in tabele
1.1. Comanda INSERT
Comanda INSERT permite inserarea (adaugarea) de noi inregistrari (randuri)
intr-o tabela.
Deoarece sistemul mySQL este pur relational, nu exista nici o diferenta intre
inserarea de noi date sau adaugarea lor. In ambele situatii, locul in care se face
adaugarea nu este precizat, nefiind relevant. La sistemele care nu sunt pur
relationale (cum este dBase sau FoxPro) operatia de adaugare semnifica
adaugarea la sfarsitul unei tabele, pe cand insertia inseamna inserarea intre alte
doua inregistrari existente.
Comanda INSERT din mySQL are sintaxa de baza:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_nume [(col_nume,...)]
VALUES (expresie,...),(...),...
Parametrii au urmatoarea semnificatie:

36

LOW_PRIORITY - se foloseste pentru a intarzia scrierea efectiva a datelor


in tabela pana cand alti utilizatori nu mai citesc date din tabela. Acest lucru
avantajeaza citirea dar intarzie, semnificativ pentru o tabela foarte utilizata,
scrierea. Efectul este blocarea executiei pana cand se reuseste scrierea
efectiva.
DELAYED - are actiune opusa parametrului precedent. Inregistrarea care
trebuie adaugata este pusa intr-o coada de asteptare pe server si controlul
revine la client, ca si cum scrierea ar fi fost facuta efectiv. Avantajul consta
in timpul mic de executie a comenzii INSERT pe o tabela utilizata intensiv.
Dezavantajul consta in incarcarea serverului cu o operatie in plus si in
pierderea datelor daca serverul se opreste neasteptat. Din aceasta cauza

ABD

l
l

parametrul este folosit doar cand este cu adevarat necesar.


IGNORE - este util daca se insereaza mai multe inregistrari simultan (in
acest caz lista de dupa VALUES va contine mai multe seturi de date in
paranteze, departite prin virgula). In mod obisnuit, MySQL raporteaza
eroare si nu executa comanda care incearca adaugarea a cel putin unei
inregistrari care duplica cheia primara sau campuri cu valori unice. Prin
folosirea parametrului IGNORE inregistrarile gresite sunt ignorate, dar restul
sunt adaugate fara raportarea unei erori. Dupa executia comenzii se va
raporta doar numarul de inregistrari a caror adaugare a reusit.
INTO - este optional, se foloseste pentru compatibilitate cu alte sisteme
SQL. Datorita claritatii mai mari a interogarii se prefera totusi utilizarea lui.
tbl_nume - specifica numele tabelei unde se adauga inregistrarile.
(col_nume,...) - este o lista de coloane care specifica ordinea in care se vor
adauga datele in tabela. Prin aceasta se pot insera doar datele considerate
esentiale, restul primind valorile implicite specificate la declararea tabelei.
Daca lista lipseste, setul de date furnizat trebuie sa aiba valori pentru toate
campurile, in ordinea din declararea tabelei.
VALUES - specifica seturile de date (inregistrarile) care se vor adauga in
tabela.
(expresie, ...),(...),... - fiecare paranteza specifica datele unei inregistrari ce
va fi adaugata. Ele trebuie sa respecte numarul si ordinea coloanelor de la
declararea tabelei sau, daca e specificat, numarul si ordinea campurilor din
lisata de coloane (col_nume,...) prezentata anterior.

O sintaxa introdusa o data cu versiunea 3.22.10 permite specificarea explicita a


corespondentei intre coloane si valorile inserate:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_nume
SET col_nume1=expresie1, col_nume2=expresie2, ...
O a treia sintaxa permite adugarea automata a inregistrarilor prin selectia lor din
alte tabele:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
Optiunea SELECT va fi discutata pe larg in capitolul urmator. In principiu trebuie
retinute totusi cateva limitari:

operatia de selectie nu poate contine clauza ORDER_BY pentru ordonarea


rezultatului
datele nu pot fi selectate din aceeasi tabela in care sunt apoi inserate

1.2. Utilizare comenzii INSERT

37

ABD

Se considera baza de date Banca descrisa in capitolul anterior, cuprinzand


tabelele:
Deponent
nr_buletin char(8) NOT NULL PRIMARY KEY
cnp char(13) NOT NULL
nume char(24) NOT NULL
prenume char(24) NOT NULL
datan date
oras char(24) DEFAULT 'Timisoara'
adresa char(32)
telefon char(9)
Conturi
nr_cont char(6) NOT NULL PRIMARY KEY
nr_buletin char(8) NOT NULL
tip_cont char(3) DEFAULT 'Lei'
termen_depozit int(3) DEFAULT 0
sold int DEFAULT 0
Operatii
nr_cont char(6) NOT NULL
suma int
data timestamp
2. Modificarea datelor din tabele
2.1. Comanda UPDATE
Comanda UPDATE permite actualizarea (modificarea) valorilor dintr-o tabela.
Sintaxa acestei comenzi este:
UPDATE [LOW_PRIORITY] [IGNORE] tbl_nume
SET col_nume1=expr1,col_nume2=expr2,...
[WHERE conditie_de_actualizare]
Parametrii au urmatoarea semnificatie:

l
l

38

LOW_PRIORITY - intarzie executia comenzii UPDATE pana cand nici un alt


client nu mai citeste din tabela. Are acelasi efect ca si in cazul comenzii
INSERT.
IGNORE - nu se intrerupe executia in cazul in care se duplica chei unice la
actualizare. Inregistrarile care cauzeaza erori sunt pur si simplu ignorate.
tbl_nume - nume tabela unde are loc actualizarea
SETcol_nume1=expr1,col_nume2=expr2,... - indica acele coloane care
sunt modificate si noile lor valori. Expresiile de actualizare pot cuprinde

ABD

vechile valori ale campurilor de actualizat.


WHERE conditie_de_actualizare - indica acele coloane care sunt
actualizate, si anume doar cele pentru care conditie_de_actualizare are
valoarea adevarat. Daca clauza WHERE lipseste, vor fi actualizate toate
inregistrarile.

2.2. Utilizarea comenzii UPDATE


Considerand tabelele bazei de date Banca si datele adaugate in cadrul activitatii
anterioare, se vor exemplifica urmatoarele actualizari:
mysql> UPDATE Deponent
SET nume='Predescu' WHERE nr_buletin='TM123456';
mysql> SELECT * FROM Deponent;
# Prefixele telefonice ale oraselor se schimba din 0xx in 7xx:
mysql> UPDATE Deponent
SET telefon=concat('7',right(telefon, length(telefon)-1));
mysql> SELECT * FROM Deponent;

3. Stergerea datelor din tabele


3.1. Comanda DELETE
Pentru stergerea datelor din tabele se foloseste comanda DELETE.
Foarte important: datele o data sterse nu mai pot fi recuperate. Totusi, din motive
de viteza, datele nu sunt efectiv sterse din fisiere, locul ocupat de ele fiind alocat
pentru adaugarea de noi inregistrari la operatia de INSERT.
Sintaxa comazii DELETE este:
DELETE [LOW_PRIORITY] FROM tbl_nume
[WHERE conditie_de_stergere]
Parametrii au urmatoarea semnificatie:

l
l

LOW_PRIORITY - intarzie executia comenzii DELETE pana cand nici un


client nu mai citeste din tabela. Are acelasi efect ca si in cazul comenzii
INSERT.
FROMtbl_nume - specifica tabela de unde se sterg inregistrari.
WHEREconditie_de_stergere - specifica inregistrarile care vor fi sterse, si
anume cele care indeplinesc conditia logica precizata. Atentie! Daca clauza
WHERE este omisa se vor sterge toate inregistrarile din tabela.

3.2. Utilizarea comenzii DELETE


Considerand tabelele bazei de date Banca si datele adaugate in cadrul activitatii
anterioare, se vor exemplifica urmatoarele stergeri:

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;

'2010 conf. dr. ing. Dan Pescaru

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

SQL_BUFFER_RESULT - se foloseste pentru a forta serverul sa creeze o


tabela temporara cu rezultatul interogarii. Acest lucru este util in cazul in
care tabela interogata este utilizata intensiv in retea si se doreste
deblocarea rapida a ei pentru accesul altor clienti. In mod obisnuit nu este
necesar.
HIGH_PRIORITY - da prioritate interogarii curente fata de alte interogari
INSERT sau UPDATE aflate in coada de asteptare pentru acea tabela.
DISTINCT - Permite eliminarea randurilor duplicate din selectie.

ABD
l

ALL - Rezultatul selectiei va cuprinde si randuri duplicate. Daca nu se


specifica nici DISTINCT, nici 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.
INTO {OUTFILE | DUMPFILE} 'nume_fisier' - permite salvarea rezultatului
unei interogari sub forma unui fisier text. Fisierul va fi creat pe server
(trebuie sa nu existe), implicit in directorul bazei de date. Optiunea
OUTFILE specifica salvarea tuturor randurilor rezultatului formatate pe
coloane, pe cand DUMPFILE permite salvarea unui singur rand fara
formatare. DUMPFILE este util pentru a salva campuri de tip BLOB
(imagini, sune, video).
FROMreferinte_tabele - specifica tabela sau tabelele din care se
selecteaza datele. In cazul in care referinta cuprinde mai multe tabele
operatia este una de JOIN.
WHEREconditie_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 functiile prezentate in capitolul 3.
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.

1.2. Utilizarea conditiilor de selectie


Conditiile de selectie permit regasirea datelor necesare intr-un anumit context. La
scrierea acestor conditii vor putea fi folosie functiile prezentate in Capitolul 3. De
asemenea, la folosirea operatorilor de comparatie se va tine seama de
observatiile facute acolo.
1.3. Ordonarea rezultatului
In multe situatii este necesara ordonarea rezultatelor instructiunii SELECT.
Un exemplu concludent este reprezentat de lista rezultatelor la un concurs. Daca
la concurs s-au prezentat 2000 de candidati si rezultatul este afisat intr-o lista
neordonata, probabil ca ar fi necesar ca un candidat sa piarda jumatate de zi
pentru a se regasi pe lista.
Ordonarea se poate controla prin clauza ORDER BY. Este important de inteles
ca aceasta clauza presupune o operatie suplimentara, mare consumatoare de
timp.

42

ABD

1.4. Folosirea alias-urilor (poreclelor)


Pentru a simplifica scrierea instructiunilor se pot folosi denumiri prescurtate,
numite alias-uri (porecle). Ele pot fi folosite atat pentru a desemna tabele cat si
coloane.
O utilitate deosebita o au in cazul combinarii datelor din mai multe baze de date,
pentru a inlocui nume de tipul
nume_baza_de_date2.nume_tabela_1.nume_coloana_3, in cazul coloanelor
calculate sau in cazul operatiilor de JOIN (vor fi discutate in capitolul urmator).
Sintaxa de definire a unui alias este urmatoarea:
SELECT alias_t1.nume_coloana1 [AS] alias_c1,... FROM tabela1
alias_t1ORDER BY alias_c1 ...;
Dupa cum se observa, alias-urile definite pentru tabele pot fi folosite in partea de
specificare a coloanelor, iar alias-urile coloanelor pot fi folosite in clauze ORDER
BY sau HAVING (va fi discutata in capitolul urmator).
'2010 conf. dr. ing. Dan Pescaru

43

ABD

Cap.8. Interogari avansate


1. Selectarea datelor din mai multe tabele. Operatia JOIN.
1.1.Selectarea datelor din mai multe tabele.
1.2. Tipuri de JOIN.
2. Extragerea informatiilor de sumarizare.
1. Selectarea datelor din mai multe tabele. Operatia de JOIN.
1.1. Selectarea datelor din mai multe tabele.
Comanda SELECT in forma studiata in capitolul anterior permite efectuarea
operatiei de selectare a datelor dintr-o singura tabela (implementeaza operatorul
SELECT din algebra relationala).
Limbajul SQL foloseste insa tot comanda SELECT pentru implementarea
operatorului JOIN. Acest operator este definit de algebra relationala pentru a
permite colectarea datelor din tabelele aflate in legaturi relationale.
Folosirea comenzii SELECT pentru a face JOIN presupune specificarea in
clauza FROM a tabelelor de unde se preiau datele si, in lista de proiectie, a
campurilor care vor face parte din rezultat.
In acest caz forma generala a instructiunii SELECT este:
SELECT lista_campuri
FROM lista_tabele
WHERE conditii_join AND conditii_selectie
ORDER BY ...
...
Parametrii au urmatoarea semnificatie:

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

conditii_selectie - specifica conditiile de filtrare a rezultatului dupa


adunarea datelor din tabele.

1.2. Tipuri de JOIN


Variantele posibile la operatia de JOIN se refera la modul in care sunt tratate
inregistrarile care nu au corespondenta in fiecare tabela legata relational de
tabelele in care inregistrarile respective apar.
Principial, rezultatul operatiei de JOIN poate include sau nu inregistrarile fara
corespondenta. In primul caz operatia se numeste OUTER JOIN, iar in cel de al
doilea INNER JOIN.
Operatia de OUTER JOIN va completa automat campurile care lipsesc din
tabela corespondenta cu valoarea NULL. Un OUTER JOIN are la randul sau
doua varinate. Ambele includ toate inregistrarile care au corespondenta in
ambele parti ale relatiei. In plus, LEFT OUTER JOIN va include in rezultat si
inregistrarile din tabela stanga care nu au corespondent in tabela din partea
dreapta a relatiei. In opozitie, RIGHT OUTER JOIN va include in rezultat si
inregistrarile din tabela din dreapta care nu au corespondent in tabela din partea
stanga.
Operatia de INNER JOIN nu are variate pe stanga sau pe dreapta, pentru ca in
ambele cazuri se vor include in rezultat doar capurile care au corespondent la
ambele capete ale relatiei.
Daca lista de tabele din SELECT cuprinde doar tabele despartite prin virgula se
considera implicit o operatie de INNER JOIN.
Specificarea explicita a tipului de JOIN are sintaxa:
SELECT lista_campuri
FROM tabela [INNER JOIN | LEFT OUTER JOIN | RIGHT OUTER JOIN]
tabela ON conditie_join ...
WHERE conditii_selectie
ORDER BY ...
...
In cazul acesta se observa ca specificarea conditiei de join (legatura relationala
dintre tabele) se face dupa fiecare pereche de tabele printr-o clauza ON
separata. In mod natural, clauza WHERE va contine aici doar conditiile
suplimentare de filtrare a inregistrarilor dorite.
2. Extragerea informatiilor de sumarizare.
Informatiile de sumarizare reprezinta informatii globale despre datele din tabele.
Informatiile de sumarizare se extrag pe grupuri de inregistrari. Mai mult, ele nu
au sens decat in contextul gruparii datelor.
Pentru a grupa datele se va utiliza urmatoarea sintaxa pentru instructiunea
SELECT:
45

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

COUNT(*) - numara cate inregistrari sunt selectate in fiecare grup.


COUNT(DISTINCT expr) - numara cate inregistrari pentru care expresia are
o valoare distincta sunt selectate in fiecare grup.
AVG(expr) - calculeaza media aritmetica a valorilor expresiei pentru
inregistrarile din fiecare grup.
MIN(expr) - calculeaza valoarea minima a expresiei pentru toate
inregistrarile din fiecare grup.
MIN(expr) - calculeaza valoarea maxima a expresiei pentru toate
inregistrarile din fiecare grup.
SUM(expr) - calculeaza suma valorilor expresiei pentru toate inregistrarile
din fiecare grup.

Atentie! Nu este permisa combinarea functiilor de sumarizare cu campurile din


tabele decat in cazul in care campurile respective au o valoare unica in cadrul
grupului. In cele mai multe cazuri acestea vor fi campurile din clauza GROUP
BY.
'2010 conf. dr. ing. Dan Pescaru

46

ABD

Cap.9. Biblioteci mySQL. Accesul concurent la


date.
1. Implemetarea programelor client.
1.1. Suport ODBC.
1.2. Suport JDBC.
1.3. Biblioteca MySQL C.
1.4. Suport Pearl.
1.5. Suport PHP.
2. Accesul concurent la date.
2.1. Tranzactii. Blocarea/deblocarea unei tabele.
2.2. Replicarea datelor.
1. Implemetarea programelor client.
1.1. Suport ODBC.
Standardul ODBC (Open DataBase Conectivity) a fost dezvoltat de firma
Microsoft in scopul de a permite aplicatiilor Windows sa se conecteze la baze de
date relationale. El reprezinta un strat intermediar (un driver) ce se interpune
intre client si baza de date.
Rolul ODBC este acela de a transforma interogarile clientului si a returna
rezultatele catre acesta. In acest sens driver-ul ODBC preia interogarile client
scrise in sintaxa ODBC SQL (apropiata de ANSI SQL) si le transforma in sintaxa
particulara a server-ului la care se face conectarea. De asemenea va tranforma
rezultatele din formatul returnat de server intr-un format ODBC. In acest fel se
realizeaza o "independenta" a clientului fata de server-ul de baza de date, acesta
din urma putand fi schimbat fara modificari substantiale la nivelul programului
client.
Sistemul MySQL pune la dispozitia programatorilor un driver numit MyODBC
care asigura suport pentru acest standard.
MyODBC este un driver de nivel scazut (Level 0) pe 32 de biti si poate fi instalat
sub Windows'95, Windows'98, WindowsNT si chiar sub mai multe variante de
Unix. Suportul pentru Unix a fost gandit in ideea ca unele sisteme, cum ar fi de
exemplu ColdFusion, ruleaza sub Unix dar necesita suport ODBC pentru
conectarea la baza de date.
Pentru mai multe informatii despre utilizarea MySQL prin ODBC pot fi consultate
la adresele:

47

The FreeODBC Pages.

ABD
l

The UnixODBC Project.

Dupa instalarea driver-ului MyODBC sub Windows se poate trece la crearea


legaturii spre baza de date MySQL dorita prin intermediul managerului ODBC
care se gaseste in Control Panel. Legatura se numeste DSN (Data Source
Name) si poate fi folosita apoi pentru a deschide conexiunea ODBC la server-ul
MySQL si apoi pentru a accesa baza de date specificata.

1.2. Suport JDBC.


Standardul JDBC (Java DataBase Conectivity) este asemanator celui prezentat
anterior si a fost creat de catre firma SUN pentru a permite conectarea clientilor
scrisi in limbajul Java la baze de date relationale.
Pentru MySQL au fost create doua drivere JDBC gratuite (numite "twz"
respectiv "mm"). Ele pot fi descarcate de la adresa:

http://www.mysql.com/Downloads/Contrib/

1.3. Biblioteca MySQL C.


Distributia standard MySQL vine cu biblioteca MySQL C API (Application
Programming Interface). Ea cuprinde functii C de conectare si interogare a
bazelor de date MySQL. Mai mult chiar, majoritatea clientilor MySQL sunt scrisi
in limbajul C.
Fiecare client C va avea alocat un buffer gestionat dinamic pentru comunicarea
cu server-ul. Acest buffer creste doar cand este necesar, astfel incat ocuparea
resurselor calculatorului este minima.
Biblioteca C defineste o serie de tipuri de date care permit comunicarea cu
server-ul:

l
l
l
l

MYSQL - structura care gestioneaza conexiunea cu server-ul.


MYSQL_RES - reprezinta raspunsul server-ului la o interogare (result set).
MYSQL_ROW - reprezentarea unei inregistrari din rezultat.
MYSQL_FIELD - informatii despre un camp al unei tabele: nume, tip,
dimensiune etc.

Principalele functii din biblioteca sunt:

48

mysql_real_connect() - realizeaza conexiunea cu server-ul

ABD
l
l
l

l
l

l
l

mysql_close() - inchide conexiunea cu severul


mysql_select_db() - selecteaza o baza de date
mysql_query() - executa o comanda SQL trimisa sub forma unui sir de
caractere
mysql_row_seek() - cauta o valoare in rezultatul unei interogari
mysql_affected_rows() - intoarce numarul de inregistrari afectate de
comenzile INSERT, UPDATE sau DELETE
mysql_errno() - intoarce codul de eroare al ultimei operatii executate
mysql_fetch_row() - preia urmatoarea inregistrare din rezultat

Mai multe informatii despre biblioteca C pentru MySQL pot fi gasite in


documentatia de la adresa:

MySQL documentation

1.4. Suport Pearl.


Suportul Pearl oferit este materializat in interfata DBI cu DBD:mysql.
DBI (DataBase Interface) este o interfata Pearl comuna multor sisteme de
gestiune a bazelor de date. In acest fel, clietii Pearl isi pastreaza independenta
fata de server-ul de baze de date in maniera asemanatoare cu ODBC si JDBC.
Pentru a se conecta la un anumit server este necesar cun DBD (DataBase
Driver). Pentru MySQL driver-ul se numeste DBD:mysql.
Interfata DBI pune la dispozitie o serie de metode printre care:

l
l
l
l

connect - realizeaza conexiunea cu server-ul MySQL


disconnect - inchide conexiunea cu server-ul
do - pregateste si executa o comanda SQL
fetchrow_array - preia urmatoarea inregistrare din rezultat sub forma unui
tablou de campuri
rows - informeaza asupra numarului de inregistrari afectate de ultima
comanda

Informatii detaliate despre interfata DBI se pot obtine la adresa:

Pearl5 DBI

1.5. Suport PHP.


PHP (Personal HomePage) este un limbaj de tip script, inglobat in pagini HTML

49

ABD

si interpretat pe server-ul de Web. Pricipalul sau scop este acela de a permite


crearea de pagini Web dinamice. In acest sens el cuprinde suport pentru mai
multe servere de baze de date printre care si MySQL.
Ca si in alte biblioteci, in PHP sunt implementate o serie de functii pentru
conectarea si comunicarea cu server-ul MySQL:

l
l
l
l

l
l

l
l

mysql_connect() - realizeaza o conexiune cu server-ul de baze de date


mysql_close() - inchide conexiunea
mysql_db_query() - trimite o comanda SQL catre server
mysql_affected_rows() - intoarce numarul de inregistrari afectate de
comenzile INSERT, UPDATE sau DELETE
mysql_num_rows() - numarul de randuri din rezultat
mysql_fetch_array() - returneaza rezultatul unei interogari sub forma unui
tablou asociativ (coloana-valoare)
mysql_fetch_object() - returneaza rezultatul sub forma unui obiect care are
ca si atribute campurile din rezultat
mysql_fetch_row() - returneaza rezultatul sub forma unui tablou
mysql_errno() - intorce codul de eroare al ultimei comenzi executate

Mai multe informatii despre PHP si utilizarea functiilor PHP-MySQL pot fi gasite
la adresa:

PHP website

2. Accesul concurent la date.


2.1. Tranzactii. Blocarea/deblocarea unei tabele.
Pentru ca mai multi clienti sa poata accesa o tabela in acelasi timp (concurent),
este necesara implementarea unui sistem de partajare a informatiilor.
In multe situatii este de asemenea necesar sa se asigure "atomicitatea" unui set
de operatii. Acest lucru permite executia in totalitate a tuturor operatiilor din set
intr-un singur pas, ca si cand ar fi vorba de o singura operatie.
Notiunea de tranzactie se refera tocmai la asigurarea executiei unui set de
operatii ca un tot unitar. O tranzactie asigura fie ca se executa toate operatiile, fie
ca nu se executa nici una.
Dezvoltatorii sistemului MySQL au decis sa nu implementeze direct un sistem
de tranzactii din motive de performanta. In schimb, s-a implementat o alta
paradigma care se refera la integritatea datelor si anume "operatiile atomice". Pe
de alta parte, datorita raspandirii utilizarii sitemului MySQL, exista planuri de a
introduce in versiunile viitoare si un sistem tranzactional, astfel incat utilizatorul
50

ABD

sa poata alege intre operatii atomice sau tanzactii.


Pe de alta parte, functie de tipul de operatii efectuate, datele vor trebui sau nu
blocate pentru a asigura accesul exclusiv al unui client. Blocarea datelor in
general este necesara daca se doreste o scriere sau o modificare a lor care ar
afecta rularea altor clienti pentru aplicatii sensibile cum ar fi gestiunea bancara
sau e-comerce.
Pentru a bloca accesul altora asupra unei tabele, MySQL pune la dispozitie
comanda LOCK care are urmatoarea sintaxa:
LOCK TABLES nume_tabela [AS alias]
{READ | WRITE}
[, nume_tabela {READ | WRITE} ...]
Corespunzator, exista si opusa ei, si anume comanda UNLOCK:
UNLOCK TABLES
Parametrii comenzii LOCK au urmatorea semnificatie:

l
l

nume_tabela - specifica tabela care va fi blocata


READ - toti clienti (inclusiv cel care blocheaza) pot doar citi, dar nu si insera
sau modifica datele din tabela
WRITE - permite scrierea sau citirea din tabela doar pentru clientul curent

Comanda UNLOCK nu are parametrii si deblocheaza automat toate tabelele


blocate de clientul curent.
Cand se decide folosirea comezii LOCK trebuie avuta in vedere blocarea tuturor
tabelelor care vor fi prelucrate.
Pentru a simula o tranzactie se poate folosi secventa:

1. Se blocheaza tabelele care fac parte din tranzactie utilizand comanda

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

Se creaza un utilizator pe calculatorul master. Acest utilizator va fi folosit


doar pentru replicare si va avea setat dreptul FILE.
Se face o copie de siguranta pentru toate tabelele care vor fi replicate.
Se seteaza optiunea log-bin in fisirul my.cnf de pe master. Pentru a avea
efect se restarteaza calculatorul master.
Se incarca manual copia de siguranta pe calculatorul slave.
Se adauga in fisierul my.cnf de pe calculatorul slave optiunile:
master-host= < nume calculator master >
master-user= < nume utilizator creat pentru replicare >
master-password= < parola pentru utilizator >
inlocuindu-se specificatiile din parantezele unghiulare <> cu valorile
concrete.

Se reporneste calculatorul slave.

Dupa efectuarea acestor pasi, calculatorul master si slave se vor sincroniza


automat.
'2010 conf. dr. ing. Dan Pescaru

52

ABD

Cap. 10 PHP - prezentare


1.1. Introducere
1.2. Comparatia cu alte sisteme

Cap 1.1. Introducere.


Limbajul PHP este un un limbaj de tip script creat special pentru Web. Liniile de
cod PHP trebuie incluse in interiorul unei pagini Web scrisa in HTML.
Limbajul PHP este un limbaj interpretat de server (server -side scripting
language). Acest lucru permite generarea flexibila a unor pagini dinamice, care
ofera informatii in timp real. Scopul este acela de a permite crearea de la simple
pagini de prezentare pana la un site e-comerce complex.
Utilizand PHP pot fi construite usor:
l
l
l
l
l
l

mecanisme de autentificatre utilizatori


sisteme de gestiune a continutului
sisteme de tip "web based e-mail"
gestionare de liste de mesaje
forumuri Web
generarea automata de documente pdf

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.

Un utilizator lanseaza prin intermediul unui navigator Web (ex: Internet


Explorer sau Netscape Navigator) o cerere HTTP (HyperText Transport Protocol)
catre un server Web pentru a pagina cu extensia PHP.

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.

Cap 1.2. Comparatia cu alte sisteme.


Limbajul PHP are multi competitori, limbaje care au fost create sau adaptate in
acelasi scop: generarea de continut dinamic pe Web. Dintre acestea cele mai
importante sunt: Perl, Microsoft ASP (Active Server Pages), JSP (Java Server
Pages) si Allaire Cold Fusion.
Fata de aceste produse, PHP are cateva avantaje importante:
l
l
l
l
l
l
l

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

Cap. 11 PHP - Instalare


1.1. Instalarea serverului Apache
1.2. Instalarea suportului PHP pentru serverul Apache
1.3. Testarea instalarii modulului de PHP
1.4. Instalarea mySQL
1.5. Informatii aditionale

Cap 1.1. Instalarea serverului Apache


A. Instalarea serverului sub Windows.
In cazul in care nu exista instalat un server Apache, se va proceda dupa
urmatoarea schema:
1. Se va aduce ultima versiune pentru Windows de la adresa:
http://www.apache.org/dist/httpd/binaries/win32/ Serverul este precompilat si se poate instala direct (ex. apache_1.3.31-win32-x86no_src.exe ).
2. Se executa programul de instalare. Se citesc conditiile de licentiere si se
accepta.
3. Se schimba directorul de instalare in C:\Apache. Daca nu exista suficient
spatiu pe discul C se poate plasa directorul de instalare si pe alt disc, spre
exemplu: D:\Apache .
4. Se alege modul de instalare "typical"
In timpul instalarii se creaza un set implicit de fisiere de configurare in subdirectorul "conf". Pentru a asigura o buna functionare, sunt necesare mici
modificari in fisierul httpd.conf (fisierele de configurare au extensia conf).
Modificarile pot fi facute cu ajutorul oricarui editor de text, spre exemplu
Notepad. Modificarile in httpd.conf sunt urmatoarele:
1. Se modifica linia ServerAdmin astfel incat sa indice propria adresa de mail.
Ex:
ServerAdmin ionescu@unMailServer.ro
2. In linia
#ServerName
se va indeparta semnul # si se va introduce numele masinii:
ServerName computer.domeniu.ro
In cazul in care calculatorul nu este conectat la Internet sau nu stiti hostname-ul sau se va introduce:
ServerName localhost
Dupa salvarea acestor schimbari, se poate incerca pornirea serverului. Pentru
aceasta, se va selecta intrarea "Start Apache" din meniul Start/Programs.

B. Instalarea serverului sub Linux.

56

ABD
In cazul in care nu exista instalat un server Apache se va proceda in felul
urmator:
l

l
l
l

Se va aduce ultima versiune (recomandat 1.3.x) pentru Linux de la adresa:


http://www.apache.org/dist/httpd/binaries/linux/
Se decomprima in directorul /usr/local/apache si apoi se intra in acest
director.
Se compileaza distributia prin comanda make
Se instaleaza cu ajutorul comenzii make install
Se modifica fisierul /usr/local/apache/conf/httpd.conf conform specificatiei
in cazul instalarii sub Windows
Se porneste serverul cu ajutorul comenzii /usr/local/apache/bin/apachectl
start

Cap 1.2. Instalarea suportului PHP pentru


serverul Apache.
Pentru a avea posibilitatea rularii scripturilor PHP pe serverul Apache va fi
necesara intalarea acestui modul. In acest scop se vor urmarii pasii:

A. Instalarea suportului PHP pentru Windows.


1. Se aduce ultima variata compleata (fisier zip) de la adresa
http://www.php.net/downloads.php (Ex. PHP 5.0.1 zip package )
2. Se dezarhiveaza distributia in directorul c:\php (daca este necesar,
utilitarul winzip se poate aduce de la adresa: http://www.winzip.com ).
3. Se copiaza fisierele c:\php\php5ts.dll, c:\php\libmysql.dll si
c:\php\ext\php_mysql.dll in directorul c:\windows\system (respectiv
c:\winnt\system32 in cazul Windows NT).
4. Pentru Windows 98 si NT 4 se instaleaza ultima variata de MDAC de la
adresa http://www.microsoft.com/data/download.htm.
5. Se copiaza fisierul c:\php\php.ini-optimized in directorul C:\windows (sau
C:\winnt) si se redenumeste php.ini.
6. Se editeaza fisirul php.ini dupa cum urmeaza:
se schimba extension_dir cu c:\php\extensions
se schimba intrarea doc_root in c:\apache\htdocs
se sterge marcajul ";" din fata liniei ";extension=php_mysql.dll"
7. se adauga in fisierul c:\apache\conf\httpd.conf urmatoarele linii:
LoadModule php5_module c:/php/php5apache.dll
AddModule mod_php5.c
AddType application/x-httpd-php .php
8. In final se porneste (re-porneste) serverul Apache.

B. Instalarea suportului PHP pentru Linux.


1. Se aduce ultima variata de la adresa http://www.php.net/downloads.php
(Ex. PHP-5.0.x.tar.gz ), x fiind numarul celei mai recente versiuni
2. Se dezarhiveaza distributia in directorul /usr/local/php-5.0.x cu ajutorul
57

ABD

3.
4.
5.
6.
7.
8.

9.

comenzii gunzip -c php-5.0.x.tar.gzip | tar xvf -.


Se schimba directorul prin cd /usr/local/php-5.0.x.
Se executa comanda de confisurare: ./configure --with-xml --withapache=../apache_1.3.x --with-curl=/usr/local/curl --withpspell=/usr/local/pspell.
Se compileaza cu ajutorul comenzii make.
Se instaleaza prin comnada make install.
Se copiaza fisierul de initializare in directorul lib prin cp
php.ini.dist /usr/local/lib/php.ini.
Se adauga in fisierul /usr/local/apache/conf/httpd.conf urmatoarele
linii:
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
In final se testeaza intsalarea pe serverul Apache prin
comanda /usr/local/apache/bin/apachectl configtest si se lanseaza serverul
prin /usr/local/apache/bin/apachectl start.

Cap 1.3. Testarea instalarii modulului de PHP


Se va crea un fisiser text c:\apache\htdocs\phptest.php (sau, pentru
Linux /usr/local/apache/htdocs/phptest.php)continand liniile:
<HTML>
<H2> Acesta este un fisier de test PHP </H2>
<P> <HR>
<? phpinfo() ?>
<P> <HR>
</HTML>
Dupa salvare se va lansa navigatorul preferat (Microsoft Internet Explorer sau
Netscape Navigator se se va incarca pagina: http://localhost/phptest.php.
Efectul ar trebui sa fie o pagina in care apar informatii despre versiunea PHP
intalata.

Cap 1.4. Instalarea mySQL.


A. Instalarea serverului mySQL sub Windows.
Pentru instalare se vor urma pasii:
1. Download fisier mysql-4.0xx-win.zip de la adresa
http://www.mysql.com/downloads. De preferabil se va aduce versiunea 52
(xx=52) sau mai noua, dar in varianta Stable Release . Diferenta intre
subversiuni consta doar in mici cosmetizari si inlaturare de erori. O solutie
mai rapida consta in aducerea unei copii din Romania, de ex. de la adresa

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.

Pentru oprirea serverului se va tasta: c:\mysql\bin\mysqladmin -u root


shutdown
Sub Winodws NT/2000/XP-Pro 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.
7. Pentru a testa serverul se vor executa comanda: c:\mysql\bin\mysqlshow
care va produce ca rezultat afisarea bazelor de date disponibile pe server

B. Instalarea serverului mySQL sub Linux.


Pentru instalare se vor urma pasii:
1. Download fisier mysql-4.0xx.tar.gz de la adresa
http://www.mysql.com/downloads. De preferabil se va aduce versiunea 21
(xx=21) sau mai noua, dar in varianta Stable Release . Diferenta intre
subversiuni consta doar in mici cosmetizari si inlaturare de erori.
2. Dezarhivare fisier mysql-4.0xx.tar.gz intr-un director temporar
(ex /tmp/download ) prin comanda gunzip -c mysql-3-4.0xx.tar.gz | tar xvf
-.
3. Se schimba directorul prin comanda cd mysql-4.0xx.
4. Se configureaza prin ./configure --prefix=/usr/local/mysql.
5. Se compileaza prin make.
6. Se instaleaza prin make install.
7. Se instaleaza baza de date sistem (mysql) prin scripts/mysql_install_db.
8. Se seteaza parola de administrator prin cd /usr/local/bin/mysql,
./safe_mysqld & si ./mysqladmin -u root password 'parola'.
9. Se testeaza instalarea prin rularea comenzii bin/mysqlshow -p.

Cap 1.5. Informatii aditionale


59

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

Cap. 12 PHP - Tipuri de date. Variabile.

2.1.1.
2.1.2.
2.1.3.
2.1.4.
2.1.5.
2.1.6.

Inserarea codului PHP intr-o pagina HTML. Taguri PHP


Generarea dinamica de continut HTML
Tipuri de date. Conversii de tip
Identificatori. Constante
Variabile utilizator. Variabile referinta. Domeniu de valabilitate
Accesarea variabilelor din form-uri HTML

Cap 2.1.1. Inserarea codului PHP intr-o pagina


HTML. Taguri PHP
Scripturile PHP sunt destinate generarii dinamice de continut in paginile de Web.
De aici rezulta faptul ca un astfel de script trebuie inclus intr-o pagina HTML. In
acest scop pot fi folosite mai multe tipuri de tag-uri HTML dupa cum urmeaza:
l

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.

Cap 2.1.2. Generarea dinamica de continut


HTML
Codul PHP nu va fi vizibil in sursa trimisa de serverul Web catre navigatorul
clientului. Acest cod va fi interpretat de catre modulul PHP din server si doar
textul generat de acest script va fi trimis mai departe de catre server.
La scrierea codului, instructiunile PHP din script vor fi terminate printr-un
separator punct si virgula ';' asemanator celor din limbajul C, C++ sau Java.
Omiterea acestul separator va genera o eroare de sintaxa.
Interpretorul de PHP va ingnora in schimb spatiile dintre instructiuni sau dintre
elementele unei instructiuni. Spre exemplu, secventele:
<?php echo "Hello"; echo "world !"; ?>
si
<?php echo
"Hello";
echo "world !" ;?>
vor genera acelasi rezultat.
Pentru claritatea codului se obisnuieste sa se adauge comentarii in care sa se
explice rolul liniilor respective. Interpretorul de PHP va ignora textul din
comentarii, el avand doar rolul de a ajuta programatorul in dezvoltarea codului
respectiv. Comentariile pot si adaugate in trei moduri:
l

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.

Pentru a exemplifica generarea dinamica de continut se va utiliza functia date()


pentru a afisa data si ora la care a fost interpretat scriptul pe server:

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

Cap 2.1.3. Tipuri de date. Conversii de tip


Limbajul PHP suporta urmatoarele tipuri de date:
l
l
l
l
l

Integer - utilizat pentru numere intregi


Double - utilizat pentru numere reale
String - utilizat pentru siruri de caractere
Array - utilizat pentru a stoca date multile de acelasi tip
Object - utilizat pentru a retine obiecte - instante ale claselor

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.

Cap 2.1.4. Identificatori. Constante


Identificatorii sunt cuvinte care denota entitati intr-un program. Exemple de
identificatori sunt: numele de variabile, de functii sau de clase. In PHP
identificatorii trebuie sa respecte urmatoarele reguli:
l

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.

PHP permite folosirea a doua tipuri de constante.


Constantele de tip valoare sunt precizate direct in expresii dependent de tipul
lor:
l
l
l

constantele intregi: 0, 100, -1320


constantele de tip double: 0.00, 3.1523, -4.5
constantele de tip sir de caractere: "sir1", 'sir2', 'sir cu "gilimele"! ', "sir cu
'apostrof'! "

Constantele cu nume se aseamana cu varibilele, dar valoarea lor nu poate fi


schimbata de-a lungul programului. Pentru a face codul scris mai lizibil se
obisnuieste ca numele varibilelor sa fie scrise in intregime cu litere mari. O
diferenta notabila fata de variabile este aceia ca numele acestora nu sunt
precedate de semnul $. Declararea cosntantelor se face cu ajutorul cuvantului
cheie define.
...
define("PI",3.14);
$unUnghi = PI;
$altUnghi = 2*PI;

Cap 2.1.5. Variabile utilizator. Variabile


referinta. Domeniu de valabilitate
Variabilele sunt locatii de memorie desemnate printr-un identificator care incepe
64

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

Global - varibilele globale, definite in afara functiilor sunt vizibile in tot


fisierul curent, mai putin in interiorul functiilor.
Locale unei functii - variabilele create in functii sunt vizibile doar in
interiorul acestora.
Globale in interiorul unei functii - acest tip de varibile sunt folosite pentru a
accesa variabilele globale cu acelasi nume.

Cap 2.1.6. Accesarea variabilelor din form-uri


HTML
Principalul mecanism de colectare a datelor de la utilizatori prin intermediul unui
site Web il reprezinta formularele HTML (HTML forms). Din acest motiv, limbajul
PHP pune accent pe facilitarea accesului la aceste date.
Un formular HTML cuprinde campuri in care utilizatorul (cel care acceseaza
pagina) poate introduce date. Pentru procesarea acestor date formularul
defineste o actiune numita submit (trimitere), care corespunde de obicei
apasarii unui buton cu acelasi titlu. Rezultatul acestei actiuni este accesarea
unei alte pagini (pagina tinta - target) care va primi automat valorile
completate in campurile formularului si le va prelucra. In cadrul subiectului
65

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.

Creati fisierul a2161.html cu urmatorul continut:


<HTML>
<HEAD>
<TITLE>Activitate 2 (form)</TITLE>
</HEAD>
<BODY>
<FORM name="primulForm" method ="post"
action="a2162.php">
<P>Date personale
<P>Nume <INPUT type="text" name="numePers" size="36"
maxlength="36"><BR>
Prenume <INPUT type="text" name ="prenumePers"
size="36" maxlength="36"><BR>
Mijlocul de transport preferat
<SELECT name="transport">
<OPTION>Masina </OPTION>
<OPTION>Trenul</OPTION>
<OPTION>Avionul</OPTION>
<OPTION>Vaporul</OPTION>
</SELECT>
<P> <INPUT type="submit" name="trimit" value="Submit">
<INPUT type="reset" name ="sterg" value="Reset">
</FORM>
</BODY>
</HTML>
66

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.

'2010 conf. dr. ing. Dan Pescaru

67

ABD

Cap. 13 PHP - Operatori si expresii

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

Cap 2.2.1. Operatori


Operatorii sunt simboluri care pot fi utilizate pentru a efectua operatii asupra
unor varibile si constante de diverse tipuri. Entitatile asupra carora se aplica un
operator se numesc operanzi. Un operator poate avea unul, doi sau chiar trei
operanzi. Majoritatea operatorilor sunt binari (au doi operanzi). In general
operatorii sunt clasificati functie de tipul datelor asupra carora actioneaza.

Cap 2.2.1.1. Operatori aritmetici


Operatorii aritmetici provin din matematica si actioneaza asupra datelor de tip
numeric.
Acestia sunt:
Operator
+
*
/
%
++
++
---

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

Operatorul % (modulo) are ca si rezultat restul impartirii numerelor transmise.


Operatorii de incrementare/decrementare sunt operatori unari care au ca

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

Cap 2.2.1.2. Operatori pe siruri de caractere


In PHP exista un singur operator pe siruri de caractere, restul operatiilor fiind
efectuate prin intermediul unor functii din biblioteca standard a limbajului. Acest
operator este operatorul de concatenare - punct '.'.
$s1 = "Sirul 1";
$s2 = "Sirul 2";
69

ABD
$s3 = $s1."-".$s2; // s3 = "Sirul 1-Sirul 2"

Cap 2.2.1.3. Operatori de asignare


Operatorii de asignare permit atribuirea de valori varibilelor. Cel mai simplu
operator este operatorul '='. El are doi operanzi: o variabila in partea stanga si
o expresie in partea dreapta. Valoarea expresiei este evaluata apoi atribuita
variabilei din partea stanga si, in final, returnata de operator. Deoarece = nu
este o intructiune PHP ci un operator, el poate intra in expresii complexe de
genul:
$a = $b = 4 + ($c = 3); // a = 7, b = 7, c=3
In plus fata de operatorul de asignare simplu, PHP pune la dispozitia
programatorilor si operatori de asignare combinati:
Operator
+=
-=
*=
/=
%=
.=

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

Cap 2.2.1.4. Operatori de referire


Varsiunea PHP 4 a introdus un nou operator si anume operatorul de referire '&'.
El este un operator unar, avand ca operand o variabila si permite legarea unui
nume de variabila de zona de memorie a varaibilei operand. Spre exemplu se
considera secventa:
$a = 3;
$b = $a; // a = 3, b = 3
$b = 5; // a = 3, b = 5
In urma acestei secvente vor exista doua variabile independente $a si $b.
Modificarea ulterioara a valorii lui $b nu afecteaza valoarea retinuta de $a.
Daca, in schimb, consideram secventa:
$a = 3;
$b = &$a; // a = 3, b = 3
$b = 5; // a = 5, b = 5
Se va observa ca $b nu este o varibila independenta ci este un nou nume
pentru variabila $a (ambele vor indica spre aceiasi zona de memorie). Orice
modificare a valorii lui $b va afecta in aceiasi masura si valoarea lui $a.

Cap 2.2.1.5. Operatori de comparare


70

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

Daca operanzii nu sunt de acelasi tip se va incerca conversia operanzilor pentru


a deveni compatibili si apoi se va face comparatia. In cazul operatorului test de
identitate '===' operanzii nu sunt considerati egali daca nu au acelasi tip.

Cap 2.2.1.6. Operatori logici


Operatorii logici sunt utilizati pentru a combina valori logici in expresii.
Acestia sunt:
Operator
!
&&
and

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

Cap 2.2.1.7. Operatori pe biti


Operatorii pe biti ajuta la prelucrarea numerelor intregi considerate ca siruri de
biti.
Acestia sunt:
Operator Denumire

71

Rezultat

ABD
~
&
|
^
<<
>>

negare pe biti
si pe biti
sau pe biti
sau exclusiv pe
biti
deplasare stanga
deplasare dreapta

~$a inverseaza valorilor tuturor bitilor lui $a


$a &$b doar biti pe 1 in $a si $b simultan sunt setati pe 1 in rezultat
$a | $b biti pe 1 in $a sau $b sunt setati pe 1 in rezultat
$a ^ $b bitii setati in $a sau $b dar nu in ambele sunt setati pe 1 in
rezultat
$a << $b deplaseaza bitii din $a la stanga cu $b pozitii
$a >>$b deplaseaza bitii din $a la dreapta cu $b pozitii

Cap 2.2.1.8. Operatori aditionali


Operatorii prezentati in acest subcapitol sunt: operatorul conditional, operatorul
de suprimare a erorilor si operatorul de executie.
Operatorul conditional are sintaxa:
conditie ? valoare_adevarata : valoare_falsa
Operatorul evalueaza mai intai expresia logica din conditie. Daca conditia este
adevarata va intoarce expresia valoare_adevarata iar in caz contrar
valoare_falsa.
Exemplu: echo ($varsta < 18) ? "adolescent" : "matur";
Operatorul de suprimare a erorilor '@' are sintaxa:
@(expresie)
El are rolul de a suprima erorile si avertismentele generate de expresia
operand.
Exemplu:
$a = ($b / 0); // genereaza avertisment de impartire la zero
$a = @($b / 0 ); // nu genereaza avertisment
In cel de al doilea caz, valoarea lui $a va fi setata pe valoare vida ( convertita la
0 ca intreg).
Operatorul de executie poate fi folosit pentru a executa o comnada pe
interpretorul de comenzi al serverului.
El consta in doua apostroafe inverse '`'intre care este plasata comanda de
executat. Exemplu `ls -al`.
Operatorul de executie actioneaza doar daca optiunea safe_mode din php.ini
este dezactivata (Off). In general acest operator nu se foloseste datorita
breselor de securitate pe care le deschide pe server.

72

ABD

Cap 2.2.2. Expresii


O definitie simpla a expresiilor PHP este urmatoarea: "expresie = orice are o
valoare". Cea mai mare parte a unui program PHP consta in expresii. Expresiile
combina operanzi si operatori de diverse tipuri: constante, variabile sau nume
de functii.
La evaluarea expresiilor operatorii se vor aplica intr-o ordine prestabilita, data
de "precedenta" lor. Tabelul urmator prezinta operatorii in ordinea inversa a
precedenteiv lor (in fata sunt cei mai putin prioritari).
Precedenta
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

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

'2010 conf. dr. ing. Dan Pescaru

74

ABD

Cap. 14 PHP - Structuri conditionale si repetitive

3.1.1. Instructiuni conditionale


3.1.1.1. Instructiunea if
3.1.1.2. Instructiunea switch
3.1.2. Instructiuni repetitive
3.1.2.1. Instructiunea while
3.1.2.2. Instructiunea do while
3.1.2.3. Instructiunea for
3.1.2.4. Tablouri PHP. Instructiunea foreach
3.1.3. Instructiuni de control pentru repetitii

Cap 3.1.1. Instructiuni conditionale


Instructiunile conditionale permit executia conditionata a secventelor de
program. In lipsa unor astfel de instructiuni ar fi practic imposil de implementat
o mare parte dintre problemele din luma reala.

Cap 3.1.1.1. Instructiunea if


Instructiunea if permite luarea de decizii privind executia unei alte instructiuni
sau a unui bloc de instructiuni inclus intre acolade ('{' si '}').
Cea mai simpla sintaxa a instructiunii if este:
if (expr)
instructiune
Expresia expr este o expresie (conditie) logica ce se evalueaza la true sau
false. Daca evaluarea conditiei are ca rezultat o valoare adevarata se va
executa instructiunea specificata, daca nu, instructiunea va fi ignorata si se va
trece mai departe.
Exemplu:
if ($nota < 5)
echo 'Examenul trebuie repetat!';
Daca expresia conditionala nu este una logica, se va face o conversie automata
la o valoare logica. Valorile numerice 0 sau 0.0, sirurile vide (""), tablourile
fara nici un element sau variabilele neinitializate vor fi evaluate la fals, restul
fiind evaluate la true.
Daca se doreste executia conditionala a mai mult de o instructiune se va utiliza
costructia de bloc, ca in exemplul urmator:
75

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;

Cap 3.1.1.2. Instructiunea switch


Instructiunea switch este similara cu o serie de instructiuni if care testeaza mai
multe valori posibile pentru o anumita expresie. Avantajul sau este o scriere
mai concisa si mai simplu de inteles si depanat. Sintaxa acestei instructiuni
este:
switch (expr) {
case valoare_1:
instructiune_1;
break;
case valoare_2:
instructiune_2;
break;
...
case valoare_n:
instructiune_n;
break;
defaut:
instructiune_default;
}
Dupa evaluarea expresiei, valoarea obtinuta este comparata cu valorile din
clauzele case. Daca se intalneste o potrivire se va continua cu executia
instructiunilor din clauzele case urmatoare, pana la intalnirea instructiunii break.
Consecinta este ca, daca instructiunile dintr-o clauza case nu se termina cu
break, se va continua executia cu instructiunile clazei urmatoare. Acest lucru se
poate utiliza pentru a executa o secventa de instructiuni comuna pentru mai
multe valori, ca si in exemplu urmator:
switch ($nota) {
case 1: case 2: case 3: case 4:
echo ' nu are bursa!';
break;
case 5: case 6:
echo ' bursa este 500000.';
break;
case 7:
echo ' bursa este 700000.';
break;
case 8: case 9:
echo ' bursa este 1000000.';
break;
77

ABD

case 10:
echo ' bursa este 1500000.';
break;
defaut:
echo 'nota nu este corecta!';

Cap 3.1.2. Instructiuni repetitive


Instructiunile repetitive permit implementarea algoritmilor care necesita
repetarea unei secvente de calcul.

Cap 3.1.2.1. Instructiunea while


Instructiunea while se foloseste pentru a implementa o bucla repetitiva cu test
initial. Ea permite executia unei instructiuni sau a unui bloc de instructiuni inclus
intre acolade ('{' si '}') si are sintaxa:
while (expr)
instructiune
Expresia expr este o expresie (conditie) logica ce se evalueaza inainte de
fiecare repetitie. Daca rezultatul evaluarii conditiei este adevarat, se va executa
instructiunea specificata apoi secventa se va relua. Daca rezultatul evaluarii
este fals, instructiunea va fi ignorata si se va trece la intructiunea de dupa
while.
Exemplu:
$i = 1;
while ($i< 5)
echo 'Numarul '.$i++."<BR>";
In cazul in care conditia este neadevarata de la inceput, instructiunea din bucla
nu se va executa de loc.
Creati fisierul a3121.php pentru a genera o tabela de conversie
valutara.
<HTML>
<HEAD>
<TITLE>Activitate 3.1.2.1.</TITLE>
</HEAD>
<BODY>
<H2>Tabela de conversie dolari/lei.</H1><P>
<?php
$curs= 33000;
$n = 50;
78

ABD

Ex. 1

echo "<TABLE border=1>";


while ($n<=5000)
{
echo "<TR>"; // se creeaza o noua linie in tabel
echo "<TD>"; // se creeaza coloana pentru valoarea in lei
echo number_format($n)." $ </TD>"; // se completeaza
valoarea in lei
echo "<TD>"; // se creeaza coloana pentru valoarea in dolari
echo number_format($n*$curs)." lei </TD> </TR>"; // se
completeaza valoarea in dolari
$n+=50; // se vor tabela valorile din 50 in 50 de dolari
}
echo "</TABLE>";
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a3121.php

Cap 3.1.2.2. Instructiunea do-while


Instructiunea do-while este asemanatoare cu instructiunea while dar se
foloseste pentru a implementa o bucla repetitiva cu test final. Ca si while, ea
permite executia unei instructiuni sau a unui bloc de instructiuni inclus intre
acolade ('{' si '}') si are sintaxa:
do

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.

Cap 3.1.2.3. Instructiunea for


Instructiunea for este inspirata din limbajul C. Ca si while, ea permite executia
unei instructiuni sau a unui bloc de instructiuni inclus intre acolade ('{' si '}') si
are sintaxa:
for (expr1; expr2; expr3)
instructiune
Prima expresie (expr1) este numita expresie de initializare si se executa o
singura data, neconditionat, la inceputul ciclului. De obicei aceasta expresie
contine atribuiri. Expr2 este o conditie logica ce se evalueaza la inceputul
fiecarei iteratii. Pentru conditie adevarata se va executa instructiunea din bucla,
daca este falsa, repetitia se va incheia si se va trece la intructiunea de dupa
for. Expr3 se numeste expresie de iterare si se evalueaza la sfarsitul fiecarei
repetari. Ea are rolul de a asigura trecerea la pasul urmator (incrementarea
contoarelor, citirea datelor urmatoare etc.).
Oricare dintre cele trei expresii pot fi vide. Daca expr3 este vida PHP o va
considera adevarata si va cicla la infinit. In acest caz trebuie asigurata o iesire
fortata din bucla utilizand una dintre instructiunile de control pentru repetitii
(vezi capitolul 3.1.3).
Exemplu de folosire a instruciunii for:
echo "Tabloul factorialelor primelor 10 numere naturale.<BR>";
echo "Definitia factorialului unui numar n este n!=1*2*3*...*n.<BR>";
echo "<TABLE border=1>";
for ($n = 1, $factorial = 1; $n <= 10; $n++)
{
echo "<TR> <TD>";
echo $n;
echo "</TD> <TD>";
$factorial *= $n;
echo $factorial;
echo "</TD> </TR>";
}

Cap 3.1.2.4. Tablouri PHP. Instructiunea foreach


Un tablou este un tip de date ce poate retine un set de valori. In PHP tabloul
va asocia fiecarei intrari o cheie prin care aceasta poate fi regasita. Cheile pot fi
numerice (in acest caz indicii creati implicit vor fi 0,1,2 ...) sau pot fi siruri de
caractere (caz in care tabloul se numeste asociativ). Valorile retinute pot avea
orice tip dar sunt de acelasi fel pentru un tablou dat.
O variabila de tip tablou poate fi creata prin constructorul array().

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>

Copiati fisierul in directorul htdocs al serverului de Web si


incarcati adresa http://localhost/a3124.php
La prelucrarea tablourilor numerice se prefera folosirea iteratiei dupa index in
genul:
echo "<UL>";
for ($i = 0; $i < count($culori); $i++)
echo "<LI>".$culori[$i]."</LI>";
echo "</UL>";

Cap 3.1.3. Instructiuni de control pentru


repetitii
In multe situatii, pentru simplificarea implementarii este necesar sa se iasa
fortat dintr-o iteratie. In acest scop limbajul PHP include trei instructiuni
speciale: continue, break si return.
Instructiunea break permite intreruperea fortata a buclei curente. Ea poate fi
folosita cu instructiunile for, foreach, while, do..while sau switch. Exemplu - se
vor genera 20 de numere aleatoare in intervalul [0-50] si se va imparti numarul
1000 la numerele generate. Generarea se va opri fortat daca se genereaza 0:
for ($i=1; $i <= 20; $i++)
{
$a = rand(0,50);
if ($a == 0)
{
echo "S-a generat 0.<BR> ";
break;
}
echo "Pasul $i: 1000 / $a = ".(1000/$a)."<BR>";
}
echo "Generare terminata!";
Instructiunea continue permite terminarea fortata a iteratiei curente si
trecerea la urmatoarea iteratie. Ea poate fi folosita cu instructiunile for, foreach,

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

Cap. 15 PHP - Functii. Formulare. Sesiuni.

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

Cap 3.2.1. Functii


Functiile sunt utilizate pentru a grupa instructiunile care executa un anumit
algoritm. Ele permit refolosirea codului ori de cate ori este nevoie de acel
algoritm intr-un program.
O functie este un modul de cod care ofera o interfata de apel, rezolva un anumit
algoritm si optional, returneaza o valoare.

Cap 3.2.1.1. Functii de biblioteca


Functiile de biblioteca reprezinta portiuni de cod gata scrise care pot fi
reutilizate ca atare de catre toti programatorii care folosesc acel limbaj. Aceste
functii rezolva cele mai comune probleme legate de scopul in care a fost
dezvoltat limbajul. In cazul PHP, scopul este acela de a crea cotinut Web
dinamic, ca atare majoritatea functiilor de biblioteca se refera la prelucrarea de
texte, lucrul cu protocoalele Internet si comunicarea cu servere de baze de
date.
Cele mai simple functii sunt cele care nu necesita parametrii de apel (valori de
prelucrat) si nu intorc nici o valoare. Apelul unei astfel de functii se face folosind
sintaxa:
nume_functie();
Numele functie identifica unic codul care va fi apelat in acel loc. Spre deosebire
de variabile, numele functiilor nu sunt "case-sensitive" deci pot fi scrise cu orice
combinatii de litere mari/mici (ex: Nume_functie sau Nume_FUNCTIE etc.)
Un exemplu in acest sens este functia phpinfo() care ofera (genereaza in
pagina) informatii referitoare la versiunea de PHP instalata in sistem si la
serverul de Web pe care aceasta ruleaza.
85

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);

Cap 3.2.1.2. Functii utilizator


Chiar daca acopera o mare clasa de algoritmi, functiile de biblioteca sunt
limitate ca numar. Deoarece clasa algoritmilor necesari rezolvarii problemelor
reale este infinita, in foarte multe situatii este necesar sa se defineasca functii
specifice acelei aplicatii, numite in continuare functii utilizator.
Declararea unei functii care nu necesita parametrii de apel se face in felul
urmator:
function nume_functie()
{
// secventa de instructiuni
}
Spre deosebire de functiile de biblioteca, functiile utilizator sunt disponibile doar
in fisierul unde sunt declarate.
Numele unei functii utilizator trebuie sa fie cat mai scurt dar, in acelasi timp, sa
dea indicatii precise asupra scopului acelei functii (algoritmului implementat). In
86

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.

Cap 3.2.1.3. Transmiterea parametrilor


Parametrii permit transmiterea datelor catre functii. Un parametru se va
comporta in interiorul functiei ca si o variabila locala acesteia. Parametrii pot
avea orice tip scalar sau tablou.
Parametrii se specifica prin nume la declararea functiei. Exemplul urmator
declara o functie care preia un tablou ca si parametru si il afiseaza intr-o lista in
pagina curenta.
function afis_tablou( $tablou, $numeTablou)
{
echo "Continut tablou $numeTablou <BR>";
echo "<UL>";
foreach ( $tablou as $indice => $element )
echo "<LI> $indice - $element </LI>";
echo "</UL>";
}
// apel functie
$dataNPers = array ( "Ionescu" => 1962, "Popescu" => 1967, "Vasilescu" =>
1978);
afis_tablou("anul nasterii", $dataNPers);
In anumite situatii functiile pot avea parametrii optionali - cu valori implicite
(predefinite). Acest lucru ajuta la scrierea unor functii care sunt usor de apelat
pentru cei care nu cunosc semnificatia tuturor parametrilor, dar in acelasi timp
permit specialistilor sa personalizeze algoritmul implementat de functie.
Parmetrii optionali se pot specifica doar la sfarsitul listei de parametrii. Dupa un
parametru optional nu mai poate urma un parametru neoptional. La declararea
unui parametru optional valoarea implicita a acestuia poate fi doar o constanta.
Urmatorul exemplu exemplifica folosirea paramtrilor optionali.
function afiseaza_titlu( $titlu, $marime = "H1", $culoare = "#000000")
{
echo "<$marime> <FONT color=\"$culoare\">".$titlu."</FONT></
$marime><P>";
}
afiseaza_titlu("Titlu cu valori implicite!");
afiseaza_titlu("Titlu cu marimea H2!","H2");
afiseaza_titlu("Titlu cu marimea H3 si culoare roz!","H3","#FF00FF");
O problema importanta legata de transmiterea parametrilor o reprezinta felul in
care aceasta are loc: prin referinta sau prin valoare.
Implicit toti parametrii sunt parametrii transmisi prin valoare. La
tansmiterea unui astfel de parametru, in momentul apelului se va crea o copie a
87

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>";

Cap 3.2.1.4. Functii recursive


Limbajul PHP ofera suport complet pentru functii recursive. O functie recursiva
este o functie care se apeleaza pe ia insasi direct sau indirect, prin intermediul
altor functii.
Utilitatea functiilor recursive iese in evidenta mai ales la implementarea
algoritmilor care prin natura lor sunt recursivi. Exemple de astfel de algoritmi
88

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.

Cap 3.2.2. Reutilizarea codului


Un scop important al ingineriei software este acela a reutilizarii codului in locul
scrierii de cod nou. Acest lucru duce de obicei la reducerea costurilor, reducerea
erorilor si cresterea standardizarii programelor produse. In mod ideal un proiect
nou se creaza prin combinarea componentelor reutilizabile in locul scrierii altora
noi, timpul de dezvoltare fiind redus drastic.
In continuare vor fi analizate cele mai importante trei deziderate obtinute prin
reutilizarea codului: costul dezvoltarii, stabilitatea si consistenta produsului.
Costul. De-a lungul duratei de viata a unui produs software s-a observat ca o
foarte mare parte din timpul de dezvoltare il reprezinta timpul alocat mentinerii,
modificarii, testarii si documentarii. In mod surprinzator, timpul cerut pentru
scrierea initiala a programului are de obicei ponderea cea mai putin
semnificativa. Din acest punct de vedere, cu cat numarul de linii de cod care
trebuiesc intretinute este mai mic, cu atat scade si costul general al produsului.
Scaderea numarului de linii scrise se poate obtine prin reutilizarea celor
existente.
Stabilitatea . Stabilitatea produsului se defineste in raport invers proportional
89

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.

Cap 3.2.2.1. Instructiunea require


Instructiunea require permite includerea unui fisier extern in interiorul unui
fisier script. Ea functioneaza asemanator clauzei #include din limbajele C si
C++. Sintaxa de apel este:
require ( "nume_fisier_reutilizat.php" );
Desi extensia fisierului care se include nu este obligatorie, prin conventie ea
este fie .php fie .inc. Din motive de securitate se prefera totusi extensia
standard .php, in acest fel fiind eliminat riscul de a dezvalui codul php la o
incarcare directa in browser a acestui fisier (fara extensia .php el nu este
interpretat).
In momentul interpretarii scriptului, apelul instructiunii require va fi inlocuit de
continutul fisierului transmis ca si parametru si apoi acesta va fi interpretat.
Acest lucru este ilustart de urmatorul exemplu:
// fisierul "reutilizabil.php"
<?
echo "<H2> Acesta este cod reutilizabil. </H2>";
?>
//fisierul "principal.php"
<?
echo "<H1> Acesta este fisierul principal. </H1><P>";
require ( "reutilizabil.php" );
echo "<P>Linie din fisierul principal.";
?>
La executiea fisierului principal.php, codul executat va fi:
<?
echo "<H1> Acesta este fisierul principal. </H1><P>";
echo "<H2> Acesta este cod reutilizabil. </H2>";
echo "<P>Linie din fisierul principal.";
90

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").

Cap 3.2.2.2. Instructiunea include


Instructiunea include este asemanatoare cu require. O deosebire importanta se
refera insa la modul in care se face includerea si interpretarea codului din
fisierul inclus.
Instructiunea require este inlocuita cu fisierul referit la incarcarea paginii,
indiferent daca executia codului va ajunge sau nu la aceasta instructiune.
Instructiunea include va fi inlocuita doar in momentul in care executia a ajuns in
acel punct. Din acest punct de vedere se prefera folosirea acestei instructiuni,
ea generand o incarcare mai mica pe server.
In varianta:
if (conditie)
{
require ("fis1.php");
}
else
{
require("fis2.php");
}
se vor expanda intai ambele ramuri ale instructiunii if, prin inlocuirea
instructiunilor require.
Spre deosevire de cazul anterior, daca se va folosi include:
if (conditie)
{
include ("fis1.php");
}
else
{
include("fis2.php");
}
se va expanda doar ramura care se va executa efectiv.

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;
?>

Cap 3.2.3. Controlul sesiunilor


Dupa cum se stie, protocolul HTTP este un protocol lipsit de informatii de stare.
Acest lucru se traduce prin faptul ca acest protocol nu are nici un mecanism
propriu prin care sa trasmita datele intre doua tranzactii. La cererea succesiva a
doua pagini de catre un utilizator catre un server de Web, nu exista nici o
posibilitate de transmitere spre cea de a doua pagina faptul ca este vorba de
catre acelasi utilizator.
Ideea de la care pleaca controlul sesiunilor este tocmai acela de a permite
urmarirea actiunilor unui utilizator pe parcursul unei sesiuni de accese catre
respectivul server de Web.
Acest lucru permite implementarea unui mecanism de tip "logging in" pentru un
utilizator, si, implicit, posibilitatea de a limita accesul la anumite pagini cu
informatii confidentiale, respectiv de a pezenta continutul paginilor personalizat
dupa preferintele utilizatorului respectiv.
Sesiunile PHP sunt gestionate prin intermediul unui numar unic (session ID)
generat aleator pe baza unui algoritm criptografic. Acest numar este generat de
catre PHP si mentinut de catre clientul de Web care a acceseaza pagini pe tot
parcursul sesiunii de lucru.
Numarul de sesiune (session ID) permite inregistrarea variabilelor de sesiune
stocate pe server. Aceste variabile sunt apoi vizibile in toate paginile acelei
sesiuni.
Pasii care se fac la utilizarea unei sesiuni sunt urmatorii:
l
l
l

92

crearea unei sesiuni


inregistrarea variabilelor sesiune
utilizarea variabilelor sesiune pentru controlul accesului sau personalizarea

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

Cap 3.2.4. Utilizare formulare si sesiuni pentru


controlul utilizatorilor
Pentru controlul utilizatorilor se poate folosi o pagina de intrare in care se
citesc, intr-un formular HTML, date despre acesta (nume, parola etc.). Datele
acestei pagini se inregistreaza ulterior ca si variabile sesiune, iar inforamtiile
obtinute se folosesc pentru personalizarea paginilor ulterioare sau pentru
controlul accesului la diverse pagini sau resurse. Exemplul urmator prezinta
tocmai acest mecanism.
Creati fisierul a3231.html pentru a citirea numelui unui utilizator.
<HTML><HEAD><TITLE>Activitate 3.2.3.1.</TITLE></HEAD>
<BODY>
<H2>Start sesiune. </H1><P>

Ex. 1

<FORM name="f1" method="post" action="a3232.php">


<B>Nume </B>
<INPUT type="text" name ="numePers" size ="36"
maxlength="36"><BR>
<P> <INPUT type="submit" name="trimit" value="Submit">
<INPUT type="reset" name ="sterg" value="Reset">
</FORM>
</BODY></HTML>
Creati fisierul a3232.php pentru startul sesiunii.
<?php
session_start();
?>
<HTML><HEAD><TITLE>Activitate 3.2.3.2.</TITLE></HEAD>
<BODY>
<?php
$utilizator = $_POST["numePers"];
echo "Bine ai venit $utilizator!<BR>";
session_register ("utilizator");
echo "<P><A href="a3233.php">Pagina personalizata.</A>
?>
</BODY>

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

'2010 conf. dr. ing. Dan Pescaru

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

Cap 4.1.1. Functii de biblioteca


Prin intermediul functiilor de biblioteca se asigura implementarea celor mai
uzuale operatii in domeniile tinta pentru un anumit limbaj de programare. In
felul acesta creste eficienta, robustetea si standardizarea programelor fara a fi
nevoie sa se complice limbajul in sine. Avantajul acestei metode este scurtarea
timpului de invatare a unui nou limbaj si cresterea eficientei compilatorul.
Limbajul PHP este livrat cu o serie de biblioteci de functii dedicate in special
controlului generarii dinamice a continutului paginilor de Web. Deoarece
numarul functiilor de biblioteca este impresionant, in continuare se vor studia
doar cele mai uzuale. Pentru aplicatii specifice se poate recurge la documentatia
oficiala de la adresa http://www.php.net/docs.php.

Cap 4.1.1.1. Functii de prelucrare tablouri


Aceste functii permit gestionarea tablourilor in diverse moduri. In general
suporta tablouri uni sau multi-dimensionale. Biblioteca aceasta este instalata
automat la instalarea PHP si nu necesita configurari ulterioare.
l

array array_count_values ( array tablou );

Functia array_count_values creaza un tablou asociativ care va avea ca si chei


valorile din tabloul primit ca si parametru si ca si valori frecventa de aparitie a
acestora.
l

array array_fill ( int index_start, int numar, tip_oarecare valoare);

Functia array_fill completeaza un tablou cu valoarea transmisa ca si parametru,


incepand cu pozitia index_start pe un numar precizat de pozitii.
l

96

bool array_key_exists ( tip_oarecare cheie_cautata, array tablou );

ABD
Functia array_key_exists testeaza daca o anumita cheie exista intr-un tablou
asociativ.
l

array array_keys ( array tablou );

Functia array_keys creaza un tablou completat cu cheile intalnite in tabloul


transmis ca si parametru.
l

array array_merge ( array tablou1, array tablou2 ...);

Functia array_merge creaza un tablou prin unirea tablourilor date ca si


parametrii. Elementele din rezultat vor fi in ordinea aparitiei paramterilor
(tablou2 se adauga la sfarsitul lui tablou1 etc.) Daca tablourile sunt asociative
cu chei de tip sir de caractere, la intalnirea unei valori comune intre tablourile 1
si 2, valoarea corespunzatoare cheii din tablou1 va fi suprascrisa de valoarea
corespunzatoare din tablou2.
l

tip_oarecare array_search ( tip_oarecare valoare_cautata , array tablou ,


[bool strict]);

Functia array_search cauta valoarea transmisa in parametrul tablou . Daca


valoarea este gasita se va returna cheia asociata (numerica sau sir de
caractere). In caz contrar se va returna valoarea logica FALSE. Datorita faptului
ca PHP interpreteaza valori precum 0 sau "" ca si FALSE, se recomanda testarea
rezultatului cu ajutorul operatorului ===. Paramterul logic optional strict
permite precizarea tipului cautarii. Daca este TRUE, valoarea gasita va trebuie
sa se conformeze si tipului valorii cautate.
l

void asort ( array tablou );

Functia asort creaza un tablou obtinut prin sortarea in ordine crescatoare a


valorilor din tabloul original, mentinand corecta asocierea valorilor cu cheile
corespondente. Pentru sortarea in ordine inversa se poate folosi arsort.
l

void ksort ( array tablou );

Functia ksort creaza un tablou obtinut prin sortarea in ordine crescatoare a


cheilor din tabloul original, mentinand corecta asocierea valorilor cu cheile
corespondente. Pentru sortarea in ordine inversa se poate folosi krsort.
l

int count ( array tablou );

Functia count returneaza numarul de elemente din tabloul transmis ca si


parametru.
l

bool print_r ( tip_oarecare variabila);

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

Cap 4.1.1.2. Functii de prelucrare date calendaristice


Aceste functii permit preluarea datelor calendaristice de pe serverul pe care
scriptul ruleaza si formatarea lor pentru afisarea in pagina. Majoritatea functiilor
prelucreaza valori de tip UNIX timestamp. Acestea sunt valori numerice
reprezentand numarul de secunde scurse intre data curenta si 1 Ianuarie 1970,
ora 00:00:00.
l

98

array getdate ( [int timestamp ] );

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 strtotime ( string time );

Functia strtotime creaza o valoare UNIX timestamp dintr-un sir specificand o


data in limba engleza conform specificatiilor GNU. Exemple de siruri time
corecte: "now", "10 September 2002", "next Thursday", "last Monday". Functia
returneaza valoarea -1 daca sirul introdus nu este corect.
l

int time ( );

Functia time returneaza valoarea UNIX timestamp pentru data curenta.


l

string date ( string format , [int timestamp ] );

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'

ziua in luna (01..31)

ora, format 1..12

ora pe 2 caractere, format 01..12

luna, cuvant ('January' ..


'December')
ora, format 0..23
ora pe doua caractere, format
00..23

minute 00..59

ziua in luna 1..31

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

ziua din saptamana, ('Monday' ..


'Sunday')
luna, text pe 3 caractere 'Jan' .. 'Dec'
secunde 00..59

numarul de zile ale lunii curente


28..31

anul pe 4 cifre

ziua din an 0..365

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

Cap 4.1.1.3. Functii matematice


Aceste functii permit efectuarea de calcule matematice, de la cele foarte simple
pana la cele complexe. Ele permit prelucrarea numerelor intregi (integer) sau
fractionare (float). Daca se doreste prelucrarea unor numere de foarte mari
dimensiuni se poate apela la biblioteca BCMath (Binary Calculator) care
considera numere reprezentate sub forma de siruri de caractere.
Pe langa functii, biblioteca matematica standard defineste de asemenea o serie
de constante foarte utile:
Nume
M_PI
M_E
M_LOG2E
M_LN2
M_SQRT2
M_EULER

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

tip_n abs ( tip_n numar );

Functia abs intoarce valoarea absoluta a numarului transmis (valoarea fara


semn). Rezultatul pastreaza tipul intreg sau float al parametrului.
100

ABD
l

float ceil ( float numar );

Functia ceil rotunjeste in sus valoarea parametrului. Desi rezultatul este intreg,
el este retunat tot sub forma de float.
l

float floor ( float numar );

Functia floor rotunjeste in jos valoarea parametrului. Desi rezultatul este intreg,
el este retunat tot sub forma de float.
l

float round ( float numar );

Functia round rotunjeste valoarea parametrului. Desi rezultatul este intreg, el


este retunat tot sub forma de float. Fractiile sub 0.5 sunt rotunjite in jos iar cele
peste 0.5 (inclusiv) sunt rotunjite in sus.
l
l
l

float cos ( float unghi );


float sin ( float unghi );
float tan ( float unghi );

Functiile cos, sin si tan calculeaza valoarea coresponedenta din unghiul dat in
radiani.
l
l

float deg2rad ( float unghi );


float rad2deg ( float unghi );

Functiile deg2rad si rad2deg convertesc unghiurile din grade in radiani si invers.


l

float exp ( float numar );

Functia exp calculaeza expresia: e la puterea numar.


l

tip_n pow ( tip_n baza ,tip_n exponent );

Functia pow calculeaza expresia: baza la puterea exponent.


l

float log ( float numar);

Functia log calculeaza logaritmul natural al numarului transmis ca si argument.


l
l

tip_n max ( tip_n numar1, tip_n nuamar2, ...);


tip_n min ( tip_n numar1, tip_n nuamar2, ...);

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

int mt_rand ( [[int min,] int max] );

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

float sqrt ( float numar );

Functia sqrt calculeaza radacina patrata din numarul transmis.


Creati fisierul a4113.php referitor la functii matematice.
<HTML>
<HEAD><TITLE>Activitate 4.1.1.3.</TITLE></HEAD>
<BODY>

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

Cap 4.1.1.4. Functii de prelucrare siruri de caractere


Aceste functii permit efectuarea de prelucrari asupra valorilor de tip string. Ele
au o importanta deosebita deoarece majoritatea operatiilor asupra paginilor de
Web se refera la prelucrarea textelor.
l

string chr ( int ascii );

Functia chr transforma un numar intre 0 si 255 intr-un sir continand caracterul
corespunzator codului ASCII al acestuia.
l

int ord ( string sir );

Functia ord returneaza un numar corespunzator codului ASCII al primului

102

ABD
caracter din sirul transmis ca si parametru.
l

array explode ( string separator, string sir );

Functia explode desparte sirul transmis ca si parametru intr-un tablou de


subsiruri, considerandu-le despartite de caracterul transmis pe post de
parametru (separator ).
l

string implode ( string lipici, array tablouSiruri );

Functia implode uneste sirurile continute in tablouSiruri. Intre fiecare siruri


unite se interpune sirul lipici.
l
l
l

string ltrim ( string sir );


string rtrim ( string sir );
string trim ( string sir );

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

void printf ( string format, tip_oarecare valoare1 ... );


string sprintf ( string format, tip_oarecare valoare1 ... );

Functiile printf si sprintf formateaza o serie de valori conform unei machete


transmise prin parametrul format. Prima functie afiseaza sirul rezultat in pagina
generata asemanator comenzii echo. Cea de a doua functie returneaza sirul fara
sa il afiseze in pagina generata. Caracterele de control pentru macheta sunt
prezentate in tabela urmatoare:
Caractere Semnificatie
%b

intreg reprezentat binar

%d
%f
%s

intreg cu semn reprezentat binar


numar in virgula flotanta
sir de caractere

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

string strstr ( string sirOriginal, string sirCautat );


string stristr ( string sirOriginal, string sirCautat );

Functiile strstr si stristr cauta prima aparitie a sirului sirCautat in sirul


sirOriginal. Daca sirul este gasit, ambele functii returneaza subsirul care incepe
pe pozitia identificata si pana la sfarsitul sirului sirOriginal. Daca sirul nu este
gasit, functiile retuneaza FALSE. Diferenta dintre cele doua functii rezida in
maniera in care se face comparatia celor doua siruri: pentru strstr se face
diferenta intre caractere mici / mari iar pentru stristr nu se face aceasta
diferenta.

103

ABD
l

int strpos ( string sirOriginal, string sirCautat );

Functia strpos intoarce pozitia subsirului sirCautat in sirOriginal. Daca subsirul


apare la inceputul sirului original, functia returneaza 0. Daca subsirul nu apare,
functia returneaza FALSE (trebuie facut test de identitate strpos(...) === false).
l

string substr ( string sir, int start, [int lungime] );

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

int strlen ( string sir );

Functia strlen intoarce lungimea (numarul de caractere) a sirului transmis ca si


parametru.
l
l

string ucfirst ( string sir );


string ucwords ( string sir );

Functiile ucfirst si ucwords transforma prima litera din primul cuvant, respectiv
prima litera din toate cuvintele din sir, in litera mare.
l
l

string strtolower ( string sir );


string strtoupper ( string sir );

Functiile strtolower si strtoupper transforma toate literele din sir in litere mici,
respectiv litere mari.

Creati fisierul a4114.php referitor la functii de prelucrarea siruri


de caractere.
<HTML>
<HEAD><TITLE>Activitate 4.1.1.4.</TITLE></HEAD>
<BODY>

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

Cap 4.1.2. Utilizare fisiere


Majoritatea aplicatiilor necesita salvarea datelor intre executii. In general exista
doua metode de a realiza acest lucru: utilizand fisiere respectiv utilizand baze
de date. Prima metoda este folosita cand datele de retinut sunt putine sau total
nestructurate (ex. text). Cea de a doua metoda se foloseste in cazul in care
volumul de date este mare, datele putand fi descrise structurat.
Un fisier poate fi prelucrat ca fisier text (detine informatii sub forma de text
ASCII organizat pe linii) sau ca fisier binar (infromatia este privita ca un sir de
octeti).
In PHP fisierele sunt tratate prin functii asemanatoare limbajului C.
Pasii care trebuie parcursi pentru scrierea intr-un fisier sunt urmatorii:
1. Deschiderea fisierului. Daca nu exista se va crea unul nou.
2. Scrierea datelor care se doresc a fi pastrate.
3. Inchiderea fisierului.
Similar, pentru citirea dintr-un fisier:
1. Deschiderea fisierului. Daca nu exista se va genera eroare.
2. Citirea datelor necesare.
3. Inchiderea fisierului.

Cap 4.1.2.1. Deschiderea si inchiderea unui fisier


Pentru deschiderea unui fisier se va utiliza functia fopen(). In general, numele
tuturor functiilor referitoare la fisiere incep cu litera 'f'.
105

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

Cap 4.1.2.2. Scrierea intr-un fisier


Scrierea intr-un fisier poate fi realizata apeland la una din cele doua functii:
fwrite sau fputs.
Functia fwrite permite scrierea intr-un fisier text sau binar a unui sir de octeti
transmisi prin intermediul unei variabile string. Observatie: doar sistemele
bazate pe Windows vor face diferenta intre fisierele binare si cele text.
Prototipul acestei functii este:
int fwrite ( int fp, string sir [, int numarOcteti] );
Daca se transmite si parametrul optional numarOcteti, se va scrie doar subsirul
de aceasta lungime de la inceputul sirului transmis. Daca lungimea sirului este
mai mica, parametrul optional va fi ignorat.
Functia returneaza numarul de octeti scrisi sau -1 daca scrirea s-a facut cu
eroare.
Functia fputs (file put string) este identica cu functia fwrite atat ca si parametrii
cat si ca actiune.
La scrierea unui sir intr-un fisier text se va face interpretarea caracterelor de
control: '\n' - new line (linie noua), '\t' - tab (spatii de aliniere) etc. Prin
intermediul acestor caractere se poate realiza formatarea textului in fisier astfel
incat sa fie mai usor de citit direct sau de prelucrat apoi prin functii specifice.

Cap 4.1.2.3. Citirea dintr-un fisier


Citirea datelor din fisiere permite regasirea informatiilor salvate si prelucrarea
lor ulterioara. Pentru citire, functiile utilizate sunt: fread, fgetc, fgets, readfile si
file.
Functia fread are prototipul:
string fread ( int fp, int numarOcteti );
Functia citeste dintr-un fisier binar un numar de numarOcteti octeti si ii
returneaza. Daca se intalneste sfarsit de fisier (eof) inainte de citirea octetilor
specificati, sirul returnat va avea o lungime corespunzatoare datelor efectiv
citite. Daca se doreste citirea intregului fisier se poate folosi apelul filesize
($numeFisier) pe post de parametru numarOcteti.
Functia fgetc permite citirea caracter cu caracter din fisierul specificat. La
intalnirea sfarsitului de fisier returneaza FALSE. Sintaxa de apel este:
string fgetc ( int fp );
Functia fgets permite citirea unei linii de text dintr-un fisier text. La intalnirea
unei erori de citire returneaza FALSE. Sintaxa de apel este:
107

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 );

Cap 4.1.2.4. Functii speciale pentru fisiere


Pe langa functiile prezentate exista o serie de alte functii menite a realiza
operatii specifice cu fisiere. In continuare vor fi prezentate cele mai utile dintre
acestea.
int copy ( string sursa, string destinatie );
Functia copy permite copierea fisierului specificat prin parametrul sursa in
fisierul destinatie . Daca operatia reuseste functia returneaza TRUE, iar daca nu
FALSE. Fisierele se specifica prin nume si nu trebuiesc deschise prin fopen in
prealabil. In exemplul urmator se face o copie de siguranta a fisierului comenzi:
$fisier = "comenzi.dat";
if (!copy($fisier, $fisier.".bak"))
echo "Nu s-a reusit crearea unei copii de siguranta pentru $fisier...<BR>");
int unlink ( string fisier );

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

@$fp = fopen ( "counter.dat", "r" );


if ( $fp === false )
$fp = fopen ( "counter.dat", "w" );
$n = fgets ( $fp );
$n = $n+1;
fclose ( $fp );
$fp = fopen( "counter.dat", "w" );
fputs ( $fp, $n );
fclose ( $fp );
echo "accesul cu numarul ".$n;
?>
</BODY>
</HTML>
Copiati fisierul in directorul htdocs al serverului de Web si
incarcati adresa http://localhost/a4124.php. Reicarcati apoi de
mai multe ori pagina prin apasarea butonului Refrech si observati
rezultatul.

Cap 4.1.3. Tema 4.a


A) Efectuati activitatile prezentate in acest capitol.
B) Pornind de la exemplul din Activitatea 5, scrieti un program reutilizabil (prin
include) care sa defineasca o functie:
int incrementeazaContor( string numeSite );
Functia va incrementa contorul corespunzator site-ului transmis prin numeSite
(un singur cuvant). Programul va apela procedura si va afisa apoi valoarea
returnata.
Toate contoarele vor fi retinute in acelasi fisier "contoare.dat". Acesta este un
fisier text cu structura unui fisier .ini din Windows:

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

Cap 4.2.1. MySQL. Limbajul SQL


In acest capitol vor fi analizate pe scurt cateva caracteristici ale sistemului mySQL si se va face o
recapitulare a principalelor instructiuni SQL pe care acesta le suporta.
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 (sistem de gestiune a bazelor de
date).
Printre caracteristicile care il recomanda se pot enumera:
l

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.
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.
asigura suport pentru multe limbaje de programare.
Interfete pentru clienti: C, C++, Eiffel, Java, Perl, PHP, Python
este multiplatforma.
Sunt suportate urmatoarele sisteme de operare: Linux, Win95, Win98, WinNT, Win2000, AIX,
DEC Unix, HP -UX, Mac OS XServer, OS2 Warp, Solaris, SCO UnixWare etc.

Cap 4.2.1.1. Baze de date. Tabele


n conceptia relationala o baza de date este formata dintr -o colectie de relatii (tabele , fisiere de
date) asupra carora se aplica o colectie de operatori pentru a gestiona datele continute de relatii.
Principiile algebrei relationale au fost stabilite de F. C. Codd n 1970. Ea reprezinta fundamentarea
matematica a bazelor de date relationale.
Cel mai facil client pentru conectarea la serverul de mySQL este cel tip linie de comanda care face
parte din kit-ul standard de instalare mySQL. El se numeste mysql.exe si permite conectarea atat
local cat si la un server la distanta. In continuare, comenzile si exemplele se vor rula de la
prompterul afisat dupa conectarea la server.

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;

Cap 4.2.1.2. Utilizatori si privilegii


La un server mySQL se pot conecta mai multi utilizatori in diverse scopuri. Pentru a asigura
securitatea datelor intre utilizatori, respectiv securitatea generala a serverului, mySQL are
implementat un sistem de privilegii .
Functia pricipala a sistemul de privilegii al MySQL este aceea de a autentifica si autoriza utilizatorii
conectati la server. Autorizarea se refera la permisiunea de a rula interogari precum SELECT,
INSERT, UPDATE sau DELETE. O clasa aparte de privilegii se refera la drepturile de administrare si
de interactionoare cu sistemul de operare.
Termenul privilegiu denota in general un drept al unui utilizator de a actiona intr -un anumit fel
asupra unui obiect al bazei de date (tabela, camp, index etc.).
Regula de baza la stabilirea privilegiilor este urmatoarea: un utilizator (sau proces) trebuie sa aiba
cel mai scazut nivel de privilegii, suficient pentru a putea executa sarcinile care i -au fost alocate.
Gestiunea sistemului de privilegii al mySQL se realizeaza in principal prin comanda GRANT .
Aceasta comanda permite crearea utilizatorilor si/sau stabilirea, respectiv modificarea privilegiilor
acestora pe patru nivele de privilegii:
- Global - se aplica tuturor bazelor de date existente pe un server
- Database - se aplica tuturor tabelelor dintr -o baza de date
- Table - se aplica tuturor coloanelor dintr -o tabela
- Column - se aplica doar coloanelor specificate explicit
Forma generala a comenzii GRANT este:

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

Cap 4.2.1.3. Adaugarea, modificarea si stergerea datelor


Adaugarea de noi inregistrari (randuri) intr -o tabela se face prin comanda INSERT. Exista trei
forme de baza ale acestei comenzi:
mysql> INSERT [INTO ] tbl_nume [(col_nume1,...)] VALUES (expresie1,...),(...),...
mysql> INSERT [INTO ] tbl_nume SET col_nume1 =expresie1, col_nume2=expresie2, ...
mysql> INSERT [INTO ] tbl_nume [(col_name,...)] SELECT ...
tbl_nume - specifica numele tabelei unde se adauga inregistrarile.
(col_nume1,...) - este o lista de coloane care specifica ordinea in care se vor adauga datele in
tabela. Prin aceasta se pot insera doar datele considerate esentiale, restul primind valorile implicite
specificate la declararea tabelei. Daca lista lipseste, setul de date furnizat trebuie sa aiba valori
pentru toate campurile, in ordinea din declararea tabelei.
(expresie1, ...),(...),... - fiecare paranteza specifica datele unei inregistrari ce va fi adaugata. Ele
trebuie sa respecte numarul si ordinea coloanelor de la declararea tabelei sau, daca e specificat,
numarul si ordinea campurilor din lisata de coloane (col_nume1,...) prezentata anterior.
SELECT - permite specificarea datelor care vor fi adaugate prin selectarea lor din alte tabele
Pentru modificarea datelor existente se va folosi comanda UPDATE . Sintaxa acestei comenzi este:
mysql> UPDATE tbl_nume SET col_nume1=expr1,col_nume2=expr2,... [WHERE
conditie_de_actualizare]
WHERE conditie_de_actualizare - indica acele coloane care sunt actualizate, si anume doar
cele pentru care conditie_de_actualizare are valoarea adevarat. Daca clauza WHERE lipseste, vor
fi actualizate toate inregistrarile !
Pentru stergerea datelor din tabele se foloseste comanda DELETE.
Foarte important: datele o data sterse nu mai pot fi recuperate.
mysql> DELETE FROM tbl_nume [ WHERE conditie_de_stergere]
FROM tbl_nume - specifica tabela de unde se sterg inregistrari.
WHERE conditie_de_stergere - specifica inregistrarile care vor fi sterse, si anume cele care
indeplinesc conditia logica precizata. Atentie! Daca clauza WHERE este omisa se vor sterge toate
inregistrarile din tabela !

Cap 4.2.1.4. Interogari 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.
O sintaxa simplificata a comenzii SELECT este urmatoarea:
mysql> SELECT [DISTINCT | ALL] expresie_de_selectie,...
[FROM referinte_tabele ]
[WHERE conditie_selectie]
[ORDER BY {intreg_pozitiv | nume_col | formula} [ASC | DESC] ,...]
Parametrii ei au urmatoarea semnificatie:
DISTINCT - Permite eliminarea randurilor duplicate din selectie.
ALL - Rezultatul selectiei va cuprinde si randuri duplicate. Daca nu se specifica nici DISTINCT, nici

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

mysql> DROP DATABASE IF EXISTS Biblioteca;


mysql> CREATE DATABASE Biblioteca;
mysql> USE Biblioteca
mysql> CREATE TABLE Carti (
mysql> ISBN char(13) PRIMARY KEY,
mysql> titlu char(64) NOT NULL,
mysql> autori char(64) NOT NULL,
mysql> data_aparitiei date,
mysql> nr_pagini int,
mysql> poza_coperta char(64) DEFAULT 'nu',
mysql> cod_editura char(3),
mysql> cod_domeniu char(3)
mysql> );
mysql> CREATE TABLE Edituri (
mysql> cod_editura char(3) PRIMARY KEY,
mysql> nume char(64) NOT NULL,
mysql> adresa char(64),
mysql> telefon char(24)
mysql> );
mysql> CREATE TABLE Domenii (
mysql> cod_domeniu char(3) PRIMARY KEY,
mysql> denumire char(36) NOT NULL
mysql> );
mysql> INSERT INTO Edituri VALUES ("OUP", "Oxford University Press", "UK", "+44
(0) 1536 741519");
mysql> INSERT INTO Domenii VALUES ("IST", "ISTORIE");
mysql> INSERT INTO Carti VALUES ("0198731744", "Origins of the French
Revolution",
mysql> "William Doyle", "1999 -07-01",276,"frenchRev.jpg","OUP","IST");
mysql> SELECT * FROM Carti, Edituri, Domenii
mysql> WHERE Carti.cod_editura=Edituri.cod_editura AND
Carti.cod_domeniu=Domenii.cod_domeniu;
mysql> GRANT all ON Biblioteca.* TO webcititor@localhost IDENTIFIED BY
'pAroLA!';

Cap 4.2.2. Utilizare unei baze de date mySQL in PHP


In multe aplicatii care necesita stocarea datelor solutia utilizarii fisierelor nu este convenabila. La
utilizarea fisierelor pentru date complexe apar urmatoarele probleme:
l

115

Fisierele de mari dimensiuni sunt parcurse extrem de incet

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.

Cap 4.2.2.1. Conectarea la server


Pentru a putea interoga o baza de date, o pagina PHP trebuie sa stabileasca in prealabil o
conexiune cu serverul de mySQL. Conexiunea poate fi privita ca un canal de comunicatie prin care
programul transmite cereri SQL iar serverul returneaza raspunsurile corespunzatoare.
Din PHP se pot stabili doua tipuri de conexiuni catre un server mySQL: persistente si
nepersistente.
Conexiunile persistente se realizeaza prin apelul functiei mysql_pconnect iar cele nepersistente
prin apelul mysql_connect . Ambele tipuri de conexiuni asigura aceiasi functionalitate. Singura
diferenta dintre ele consta in eficienta cu care se trateaza deschiderea unei conexiuni raportata la
cantitatea de resurse blocate. Concret, o conexiune persistenta se pastreaza dupa prima utilizare
chiar si dupa terminarea paginii curente sau dupa apelul mysql_close . Orice deschidere a unei noi
conexiuni cu aceiasi parametrii va reutiliza pe cea veche in locul crearii uneia noi. In opozitie cu
aceasta, o conexiune nepermanenta va fi distrusa la terminarea paginii sau la apelul mysql_close .
Avantajele conexiunilor permanente: viteza de stabilirea a conexiunilor, resimtita in timpi de
raspuns mai buni catre utilizatori. Dezavantaje: blocarea indelungata a unei conexiuni catre
server, afectand numarul de clienti care sunt acceptati spre a fi serviti.
Avantajele conexiunilor temporare: nu blocheaza conexiunea decat pe perioada interpretarii
scriptului. Dezavantaje: timpul mai mare de raspuns datorat crearii unei noi conexiuni la fiecare
apel.
Observatie: datorita faptului ca ambele conexiuni asigura aceiasi functionalitate, in cazul paginilor
comerciale se poate testa la incepul crearea de conexiuni permanente din toate paginile si apoi a le
modifica in conexiuni nepermanente daca se constata ca apar cazuri dese in care paginile nu sunt
accesibile datorita imposibilitatii stabilirii conexiunilor cu serverul de mySQL. Modificarea se poate
realiza prin simpla inlocuire a apelurilor mysql_pconnect cu apeluri mysql_connect cu aceiasi
parametri.
Sintaxa celor doua functii de conectare este foarte asemanatoare:
resource mysql_pconnect ( string server , string utilizator , string parola )
resource mysql_connect ( string server , string utilizator , string parola )
Parametri au urmatoarea semnificatie:
server - specifica numele masinii pe care ruleaza serverul de mySQL. Daca sereverul de Web si
cel de mySQL ruleaza pe aceiasi masina, numele poate fi "localhost". In cazul in care serverul de
mysQL s-a instalat pe alt port decat cel standard (3306), numarul portului se specifica dupa
numele serverului, spre exemplu "loalhost:3371".
utilizator - specifica numele utilizatorului pentru care se realizeaza conexiunea. Deoarece prin
nume serverul va stabili drepturile pe care programul le are asupra unei anumite baze de date,
acest parametru poate fi folosit pentru a creste securitatea site-ului.

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 );

Cap 4.2.2.2. Adaugarea de informatii in baza de date


Pentru adaugarea informatiei in baza de date trebuie transmisa din pagina de PHP o interogare
INSERT spre serverul de mySQL. Transmiterea (rularea) unei interogari SQL spre server se poate
face cu ajutorul functiei mysql_querry . Aceasta functie presupune existenta unei conexiuni
deschise spre server, selectia prealabila a bazei de date si existenta unor drepturi suficiente pentru
rularea interogarii.
Functia mysql_query are sintaxa:
resource mysql_query ( string query );
In cazul in care interogarea transmite inapoi un rezultat (SELECT, DESCRIBE, EXPLAIN sau
SHOW), functia returneaza un identifictor spre resursa reprezentata de rezultat. In cazul
interogarilor actiune (INSERT, DELETE, UPDATE etc.) functia va retura TRUE daca s -a executat
corect interogarea. In ambele situatii functia returneaza FALSE daca interogarea nu a putut fi
executata de server.
La compunerea interogarii trebuie avuta o grija deosebita la corectitudinea parametrilor folositi
(majoritatea valorilor vor fi preluate din formulare HTML). De asemenea, pentru a evita problemele
care apar din cauza caracterelor speciale interpretate diferit de mySQL si PHP, valorile variabilelor
trebuie transformate corespunzator prin utilizarea functiei addslashes:
string addslashes ( string parametru)
Pentru a afla numarul inregistrarilor afectate de o interogare actiune se poate folosi functi
mysql_affected_rows:
int mysql_affected_rows ( );

Creati fisierul a4222.html pentru citirea unei noi edituri:


<HTML>
<HEAD>
<TITLE> Citire editura </TITLE>
</HEAD>
<BODY>

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.

Cap 4.2.2.3. Cautarea si afisarea rezultatelor


Pentru a cauta informatii intr -o baza de date se vor utiliza interogari SELECT. Procedura de

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.

Creati fisierul a4223.html pentru cautarea unei edituri:


<HTML>
<HEAD>
<TITLE> Cautare editura </TITLE>
</HEAD>
<BODY>
<FORM name="cautEdi" method="post" action="a4223.php">
<P>Cautare EDITURA (daca nu se introduce nimic se vor afisa toate editurile!)<BR>
Denumire <INPUT type="text" name="numeEdi" size="64"
maxlength ="64"><BR>
<P> < INPUT type="submit" name="trimit" value="Submit" >
<INPUT type ="reset" name="sterg" value ="Reset" >
</FORM>
</BODY>
</HTML>
Creati fisierul a4223.php cu urmatorul continut:
<HTML>
<HEAD>
<TITLE> Afisare editura </TITLE>
</HEAD>
<BODY>
<H1> Afisare rezultat la cautare editura</H1>
<HR>
<?php
$numeEdi = addslashes ( trim ( $HTTP_POST_VARS["numeEdi"] ) );
echo "Se cauta editura cu numele: " .$numeEdi."<BR>";
@ $bd = mysql_connect ( "localhost", "webcititor", "pAroLA!");
if ( !$bd )

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.

Cap 4.2.3. Tema 4.b


A) Efectuati activitatile prezentate in acest capitol.
B) Creati pagini pentru adaugarea si vizualizarea de carti (2 formulare si 2 fisiere php pentru
prelucrarea lor). La adaugarea unei noi carti se va testa existenta campurilor cod_editura si
cod_domeniu in tablele Edituri respectiv Domenii inainte de a face adaugarea (se vor rula in
prealabil 2 interogari SELECT si, daca ele returneaza corect se va executa interogarea INSERT).
Raspunsul la aceasta tema va consta in numele celor patru fisiere si observatiile referitoare la
problemele intampinate, fisierele urmand sa fie transmise prin e- mail la adresa dan@cs.upt.ro.
<< Cuprins
'2010 conf. ing. Dan Pescaru

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;

Cap 4.2.1.2. Utilizatori si privilegii


La un server mySQL se pot conecta mai multi utilizatori in diverse scopuri. Pentru a asigura
securitatea datelor intre utilizatori, respectiv securitatea generala a serverului, mySQL are
implementat un sistem de privilegii .
Functia pricipala a sistemul de privilegii al MySQL este aceea de a autentifica si autoriza utilizatorii
conectati la server. Autorizarea se refera la permisiunea de a rula interogari precum SELECT,
INSERT, UPDATE sau DELETE. O clasa aparte de privilegii se refera la drepturile de administrare si
de interactionoare cu sistemul de operare.
Termenul privilegiu denota in general un drept al unui utilizator de a actiona intr -un anumit fel
asupra unui obiect al bazei de date (tabela, camp, index etc.).
Regula de baza la stabilirea privilegiilor este urmatoarea: un utilizator (sau proces) trebuie sa aiba
cel mai scazut nivel de privilegii, suficient pentru a putea executa sarcinile care i -au fost alocate.
Gestiunea sistemului de privilegii al mySQL se realizeaza in principal prin comanda GRANT .
Aceasta comanda permite crearea utilizatorilor si/sau stabilirea, respectiv modificarea privilegiilor
acestora pe patru nivele de privilegii:
- Global - se aplica tuturor bazelor de date existente pe un server
- Database - se aplica tuturor tabelelor dintr -o baza de date
- Table - se aplica tuturor coloanelor dintr -o tabela
- Column - se aplica doar coloanelor specificate explicit
Forma generala a comenzii GRANT este:

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

Cap 4.2.1.3. Adaugarea, modificarea si stergerea datelor


Adaugarea de noi inregistrari (randuri) intr -o tabela se face prin comanda INSERT. Exista trei
forme de baza ale acestei comenzi:
mysql> INSERT [INTO ] tbl_nume [(col_nume1,...)] VALUES (expresie1,...),(...),...
mysql> INSERT [INTO ] tbl_nume SET col_nume1 =expresie1, col_nume2=expresie2, ...
mysql> INSERT [INTO ] tbl_nume [(col_name,...)] SELECT ...
tbl_nume - specifica numele tabelei unde se adauga inregistrarile.
(col_nume1,...) - este o lista de coloane care specifica ordinea in care se vor adauga datele in
tabela. Prin aceasta se pot insera doar datele considerate esentiale, restul primind valorile implicite
specificate la declararea tabelei. Daca lista lipseste, setul de date furnizat trebuie sa aiba valori
pentru toate campurile, in ordinea din declararea tabelei.
(expresie1, ...),(...),... - fiecare paranteza specifica datele unei inregistrari ce va fi adaugata. Ele
trebuie sa respecte numarul si ordinea coloanelor de la declararea tabelei sau, daca e specificat,
numarul si ordinea campurilor din lisata de coloane (col_nume1,...) prezentata anterior.
SELECT - permite specificarea datelor care vor fi adaugate prin selectarea lor din alte tabele
Pentru modificarea datelor existente se va folosi comanda UPDATE . Sintaxa acestei comenzi este:
mysql> UPDATE tbl_nume SET col_nume1=expr1,col_nume2=expr2,... [WHERE
conditie_de_actualizare]
WHERE conditie_de_actualizare - indica acele coloane care sunt actualizate, si anume doar
cele pentru care conditie_de_actualizare are valoarea adevarat. Daca clauza WHERE lipseste, vor
fi actualizate toate inregistrarile !
Pentru stergerea datelor din tabele se foloseste comanda DELETE.
Foarte important: datele o data sterse nu mai pot fi recuperate.
mysql> DELETE FROM tbl_nume [ WHERE conditie_de_stergere]
FROM tbl_nume - specifica tabela de unde se sterg inregistrari.
WHERE conditie_de_stergere - specifica inregistrarile care vor fi sterse, si anume cele care
indeplinesc conditia logica precizata. Atentie! Daca clauza WHERE este omisa se vor sterge toate
inregistrarile din tabela !

Cap 4.2.1.4. Interogari 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.
O sintaxa simplificata a comenzii SELECT este urmatoarea:
mysql> SELECT [DISTINCT | ALL] expresie_de_selectie,...
[FROM referinte_tabele ]
[WHERE conditie_selectie]
[ORDER BY {intreg_pozitiv | nume_col | formula} [ASC | DESC] ,...]
Parametrii ei au urmatoarea semnificatie:
DISTINCT - Permite eliminarea randurilor duplicate din selectie.
ALL - Rezultatul selectiei va cuprinde si randuri duplicate. Daca nu se specifica nici DISTINCT, nici

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

mysql> DROP DATABASE IF EXISTS Biblioteca;


mysql> CREATE DATABASE Biblioteca;
mysql> USE Biblioteca
mysql> CREATE TABLE Carti (
mysql> ISBN char(13) PRIMARY KEY,
mysql> titlu char(64) NOT NULL,
mysql> autori char(64) NOT NULL,
mysql> data_aparitiei date,
mysql> nr_pagini int,
mysql> poza_coperta char(64) DEFAULT 'nu',
mysql> cod_editura char(3),
mysql> cod_domeniu char(3)
mysql> );
mysql> CREATE TABLE Edituri (
mysql> cod_editura char(3) PRIMARY KEY,
mysql> nume char(64) NOT NULL,
mysql> adresa char(64),
mysql> telefon char(24)
mysql> );
mysql> CREATE TABLE Domenii (
mysql> cod_domeniu char(3) PRIMARY KEY,
mysql> denumire char(36) NOT NULL
mysql> );
mysql> INSERT INTO Edituri VALUES ("OUP", "Oxford University Press", "UK", "+44
(0) 1536 741519");
mysql> INSERT INTO Domenii VALUES ("IST", "ISTORIE");
mysql> INSERT INTO Carti VALUES ("0198731744", "Origins of the French
Revolution",
mysql> "William Doyle", "1999 -07-01",276,"frenchRev.jpg","OUP","IST");
mysql> SELECT * FROM Carti, Edituri, Domenii
mysql> WHERE Carti.cod_editura=Edituri.cod_editura AND
Carti.cod_domeniu=Domenii.cod_domeniu;
mysql> GRANT all ON Biblioteca.* TO webcititor@localhost IDENTIFIED BY
'pAroLA!';

Cap 4.2.2. Utilizare unei baze de date mySQL in PHP


In multe aplicatii care necesita stocarea datelor solutia utilizarii fisierelor nu este convenabila. La
utilizarea fisierelor pentru date complexe apar urmatoarele probleme:
l

123

Fisierele de mari dimensiuni sunt parcurse extrem de incet

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.

Cap 4.2.2.1. Conectarea la server


Pentru a putea interoga o baza de date, o pagina PHP trebuie sa stabileasca in prealabil o
conexiune cu serverul de mySQL. Conexiunea poate fi privita ca un canal de comunicatie prin care
programul transmite cereri SQL iar serverul returneaza raspunsurile corespunzatoare.
Din PHP se pot stabili doua tipuri de conexiuni catre un server mySQL: persistente si
nepersistente.
Conexiunile persistente se realizeaza prin apelul functiei mysql_pconnect iar cele nepersistente
prin apelul mysql_connect . Ambele tipuri de conexiuni asigura aceiasi functionalitate. Singura
diferenta dintre ele consta in eficienta cu care se trateaza deschiderea unei conexiuni raportata la
cantitatea de resurse blocate. Concret, o conexiune persistenta se pastreaza dupa prima utilizare
chiar si dupa terminarea paginii curente sau dupa apelul mysql_close . Orice deschidere a unei noi
conexiuni cu aceiasi parametrii va reutiliza pe cea veche in locul crearii uneia noi. In opozitie cu
aceasta, o conexiune nepermanenta va fi distrusa la terminarea paginii sau la apelul mysql_close .
Avantajele conexiunilor permanente: viteza de stabilirea a conexiunilor, resimtita in timpi de
raspuns mai buni catre utilizatori. Dezavantaje: blocarea indelungata a unei conexiuni catre
server, afectand numarul de clienti care sunt acceptati spre a fi serviti.
Avantajele conexiunilor temporare: nu blocheaza conexiunea decat pe perioada interpretarii
scriptului. Dezavantaje: timpul mai mare de raspuns datorat crearii unei noi conexiuni la fiecare
apel.
Observatie: datorita faptului ca ambele conexiuni asigura aceiasi functionalitate, in cazul paginilor
comerciale se poate testa la incepul crearea de conexiuni permanente din toate paginile si apoi a le
modifica in conexiuni nepermanente daca se constata ca apar cazuri dese in care paginile nu sunt
accesibile datorita imposibilitatii stabilirii conexiunilor cu serverul de mySQL. Modificarea se poate
realiza prin simpla inlocuire a apelurilor mysql_pconnect cu apeluri mysql_connect cu aceiasi
parametri.
Sintaxa celor doua functii de conectare este foarte asemanatoare:
resource mysql_pconnect ( string server , string utilizator , string parola )
resource mysql_connect ( string server , string utilizator , string parola )
Parametri au urmatoarea semnificatie:
server - specifica numele masinii pe care ruleaza serverul de mySQL. Daca sereverul de Web si
cel de mySQL ruleaza pe aceiasi masina, numele poate fi "localhost". In cazul in care serverul de
mysQL s-a instalat pe alt port decat cel standard (3306), numarul portului se specifica dupa
numele serverului, spre exemplu "loalhost:3371".
utilizator - specifica numele utilizatorului pentru care se realizeaza conexiunea. Deoarece prin
nume serverul va stabili drepturile pe care programul le are asupra unei anumite baze de date,
acest parametru poate fi folosit pentru a creste securitatea site-ului.

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 );

Cap 4.2.2.2. Adaugarea de informatii in baza de date


Pentru adaugarea informatiei in baza de date trebuie transmisa din pagina de PHP o interogare
INSERT spre serverul de mySQL. Transmiterea (rularea) unei interogari SQL spre server se poate
face cu ajutorul functiei mysql_querry . Aceasta functie presupune existenta unei conexiuni
deschise spre server, selectia prealabila a bazei de date si existenta unor drepturi suficiente pentru
rularea interogarii.
Functia mysql_query are sintaxa:
resource mysql_query ( string query );
In cazul in care interogarea transmite inapoi un rezultat (SELECT, DESCRIBE, EXPLAIN sau
SHOW), functia returneaza un identifictor spre resursa reprezentata de rezultat. In cazul
interogarilor actiune (INSERT, DELETE, UPDATE etc.) functia va retura TRUE daca s -a executat
corect interogarea. In ambele situatii functia returneaza FALSE daca interogarea nu a putut fi
executata de server.
La compunerea interogarii trebuie avuta o grija deosebita la corectitudinea parametrilor folositi
(majoritatea valorilor vor fi preluate din formulare HTML). De asemenea, pentru a evita problemele
care apar din cauza caracterelor speciale interpretate diferit de mySQL si PHP, valorile variabilelor
trebuie transformate corespunzator prin utilizarea functiei addslashes:
string addslashes ( string parametru)
Pentru a afla numarul inregistrarilor afectate de o interogare actiune se poate folosi functi
mysql_affected_rows:
int mysql_affected_rows ( );

Creati fisierul a4222.html pentru citirea unei noi edituri:


<HTML>
<HEAD>
<TITLE> Citire editura </TITLE>
</HEAD>
<BODY>

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.

Cap 4.2.2.3. Cautarea si afisarea rezultatelor


Pentru a cauta informatii intr -o baza de date se vor utiliza interogari SELECT. Procedura de

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.

Creati fisierul a4223.html pentru cautarea unei edituri:


<HTML>
<HEAD>
<TITLE> Cautare editura </TITLE>
</HEAD>
<BODY>
<FORM name="cautEdi" method="post" action="a4223.php">
<P>Cautare EDITURA (daca nu se introduce nimic se vor afisa toate editurile!)<BR>
Denumire <INPUT type="text" name="numeEdi" size="64"
maxlength ="64"><BR>
<P> < INPUT type="submit" name="trimit" value="Submit" >
<INPUT type ="reset" name="sterg" value ="Reset" >
</FORM>
</BODY>
</HTML>
Creati fisierul a4223.php cu urmatorul continut:
<HTML>
<HEAD>
<TITLE> Afisare editura </TITLE>
</HEAD>
<BODY>
<H1> Afisare rezultat la cautare editura</H1>
<HR>
<?php
$numeEdi = addslashes ( trim ( $HTTP_POST_VARS["numeEdi"] ) );
echo "Se cauta editura cu numele: " .$numeEdi."<BR>";
@ $bd = mysql_connect ( "localhost", "webcititor", "pAroLA!");
if ( !$bd )

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.

Cap 4.2.3. Tema 4.b


A) Efectuati activitatile prezentate in acest capitol.
B) Creati pagini pentru adaugarea si vizualizarea de carti (2 formulare si 2 fisiere php pentru
prelucrarea lor). La adaugarea unei noi carti se va testa existenta campurilor cod_editura si
cod_domeniu in tablele Edituri respectiv Domenii inainte de a face adaugarea (se vor rula in
prealabil 2 interogari SELECT si, daca ele returneaza corect se va executa interogarea INSERT).
Raspunsul la aceasta tema va consta in numele celor patru fisiere si observatiile referitoare la
problemele intampinate, fisierele urmand sa fie transmise prin e- mail la adresa dan@cs.upt.ro.
<< Cuprins
'2010 conf. ing. Dan Pescaru

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

Cap 5.1.1. Tipuri de aplicatii e-comerce


Inainte de a lua in considerare detaliile legate de implemetarea unui site Web
comercial trebuie analizate scopurile si cerintele unui astfel de site.
Un scop stabilit apriori este acela de a produce bani.
Pornind de la acest fapt se pot identifica mai multe cai pentru a transpune
concepte comerciale pe Internet. Serviciile on -line pot fi folosite pentru a face
reclama unor produse "conventionale"; pentru a comercializa astfel de produse
in magazine virtuale; pentru a comercializa produse "digitale" gen publicatii
electronice, imagini, secvente audio sau video in format digital, produse
software etc; pentru a oferi servicii Web gen "valoare adaugata" ca o alternativa
eficienta la serviciile conventionale.

Cap 5.1.1.1. Brosuri de prezentare


Aceast tip de site-uri a aparut o data cu cristalizarea ideii de e-comerce.
Explozia acestui gen a avut loc in jurul anilor '90 dar aceste site-uri sunt
predominante si astazi.
Datorita simplitatii si pretului de cost scazut a acestor pagini precum si a
cerintelor mai scazute in ceea ce priveste securitatea, metoda este foslosita in
general ca si "punct de intrare pe Web" de mai toate companiile interesate de
aceasta tehnologie.
Un site tip "brochureware " poate fi orice, de la o carte de vizita a companiei sub
forma unei pagini Web pana la o colectie extinsa de informatii de marketing. In
general un astfel de site poate fi asimilat unui catalog de produse si oferte. In
toate situatiile, scopul unui astfel de site este acela de a facilita contactul cu
clientii si beneficiarii companiei respective.
Acest tip nu produce castiguri materiale directe dar poate creste semnificativ
aria clientilor potentiali pentru companie.
Problemele aparute la crearea unui astfel de site nu se adreseaza atat
129

ABD
implementarii (in multe situatii limbajul HTML este suficient) ci mai degraba
sunt probleme legate de marketing:
l
l

l
l
l

probleme legate de oferirea informatiilor cu adevarat importante


probleme referitoare la nivelul prezentarii, functie de segmentul de
populatie vizat
probleme legate de interactivitate
probleme legate de actualizarea informatiilor
probleme legate de evaluarea impactului noilor tehnologii folosite cat si
justificarea efortului facut

Primele doua probleme sunt strict de competenta unui specialist in marketing.


Legat de interactivitate, solutia cea mai comuna consta in oferirea unei adrese
de e-mail unde beneficiarii pot pune intrebari. In cazul acesta, o companie care
nu ofera raspuns zilnic la astfel de intrebari creaza senzatia ca desconsidera
beneficiarul respectiv, ceea ce duce in general la intreruperea relatiilor
bilaterale.
Actualizarea informatiilor este esentiala pentru a incuraja vizitele repetate la un
site comercial. In acesta problema, generarea dinamica a continutului, folosind
spre exemplu PHP, este o alternativa eficienta vizavi de actualizarea manuala a
paginilor. In plus, acesta tehnica cupride chiar si schimbarea periodica a
imaginii generale, eventual adaptarea la anotimpuri etc.
La companiile mari, problema evaluarii impactului diverselor metode de
marketing este esentiala. In cazul site-urilor tip brosura de prezentare exista
diverse optiuni pentru a realiza evaluarea: examinarea jurnalelor serverului
Web pentru evidentierea traficului inregistrat (se pot folosi ustensile tip
"WebAnalizer", ex: www.mrunix.net/webalizer), monitorizarea vanzarilor inainte
si dupa aparitia site-ului, solicitarea opiniilor clientilor care viziteaza site-ul (prin
e-mail sau formulare Web) sau chiar folosirea unui grup de "evaluatori platiti".

Cap 5.1.1.2. Comenzi prin Internet pentru marfuri si servicii


Un pas logic dupa implementarea unui site tip brosura este acela in care
serviciile sunt extinse pentru a permite comandarea directa din pagina a
produselor prezentate. Acest lucru este evident tinand cont de faptul ca un
interval mare de timp scurs intre prezentarea unui produs si oferirea
oportunitatii de a -l cumpara duce la pierdera unui procent important din
cumparatorii care au urmarit prezentarea: "un cumparator se razgandeste cu
atat mai usor cu cat are mai mult timp pentru a lua decizia de cumparare".
Posibilitatea de a ordona on -line duce atat la cresterea volumului de
cumparatori posibili cat si la scaderea solicitarii personalului implicat in vanzari.
O mare parte din munca poate fi automatizata prin legatura directa intre site si
o baza de date (ex PHP+mySQL).
Totusi, tinand cont de anumiti factori obiectivi, se poate demonstra ca nu orice
produs poate fi comercializat eficient pe Web. In mod ideal, un produs vandut
130

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).

Cap 5.1.1.3. Comert cu servicii si bunuri digitale


In majoritatea cazurilor produsele sau serviciile sunt vandute pe Web dar
livrarea lor se face prin intermediul unui curier. Cu toate acestea, exista si
bunuri si servicii care se pot tranzactiona complet prin Internet, in multe cazuri
chiar automat, fara interventie umana directa.
Cel mai clar exemplu in acest sens este chiar "informatia". In multe situatii
informatia este complet gratuita sau suportata prin servicii aditionale de
reclama. In alte cazuri, informatia este distribuita pe baza unei subscrieri.
Bunurile digitale includ: carti in format electronic (e-books), muzica in fomat
digital (ex. mp3), imagini destinate designerilor sau produse software ce pot fi
aduse direct prin Internet.
In privinta serviciilor, cele mai raspandite afaceri sunt cele de ISP (Internet
Service Provider) sau Web Hosting. Alte servicii specializate in diverse domenii
pot fi oferite chiar si sub forma de sisteme expert partial sau complet automate.
Avantajul comertului cu bunuri si servicii digitale consta mai ales in pretul
extrem de scazut si rapiditatea livrarii. Pentru afacerile mari insa pot aparea
probleme legate de latimea de banda a conexiunilor si timpul de raspuns la o
cerere.
Dezavantajul major consta in domeniul destul de restrans al bunurilor care pot
fi oferite digital.

Cap 5.1.1.4. Aplicatii de tip "valoare adaugata"


Multe afaceri de succes pe Web nu vand efectiv nici un produs or serviciu. Spre
exemplu serviciul Web pentru posta rapida UPS (www.ups.com) ofera suport
131

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

Cautati pe Web diverse site-uri internationale si din Romania care


ofera servicii comerciale.
Alcatuiti o lista cu aceste site-uri, impartite in categoriile
prezentate anterior.

Cap 5.1.2. Riscuri si probleme legate de


aplicatiile e-comerce
Orice afacere prezinta riscuri. Oriunde exista posibilitatea competitiei neloiale,
furturior si deturnarilor, dezastrelor naturale sau a altor riscuri asemanatoare.
Afacerile legate de aplicatii e-comerce au propriile categorii importante de
riscuri:
l
l
l
l
l
l
l

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.

Cap 5.1.3. Tema 5.a


A) Efectuati activitatea prezentata in Cap. 5.1.1.
B) Creati o pagina tip catalog de produse (brosura de prezentare) pentru o
categorie de produse la alegere. Pagina va fi creata dinamic folosind PHP si o
baza de date mySQL in care se retin produsele respective. Fiecare produs va
avea, pe langa o descriere a caracteristicilor, si o imagine. Imaginile se vor
retine in fisiere .jpg sau .gif intr-un subdirector IMG. In baza de date se va
retine intr-un camp numele fisierului imagine asociat produsului respectiv.
Baza de date va contine cel putin 3 produse, cu poze aferente in directorul IMG.
Raspunsul la aceasta tema va consta in prezentarea manierei in care s-a facut
afisarea unui produs si observatiile referitoare la problemele intampinate.
Fisierul SQL continand comenzile pentru crearea si popularea bazei de date
mySQL, fisierul PHP si directorul IMG vor fi comprimate si transmise prin e-mail
la adresa dan@cs.upt.ro.
<< Cuprins
'2010 conf. ing. Dan Pescaru

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

Cap 5.2.1. Utilizare cookies


Necesitatea de a pastra informatii de stare pentru o aplicatie cuprinzand mai
multe pagini php a fost discutata in capitolul referitor la sesiuni PHP. In
continuare va fi prezentata o alta metoda de a realiza prezervarea informatiilor
de stare.
Entitatile de tip cookies au fost create tocmai pentru a permite unui server de
Web sa stocheze si sa citeasca mai apoi date de pe calculatorul clientului care
ruleaza navigatorul Web. Aceste date vor fi stocate de catre navigator pe discul
clientului, intr-un director dedicat. Acest lucru permite stocarea informatiilor nu
doar pe parcursul unei sesiuni client (de la lansarea pana la oprirea
navigatorului Web) ci chiar si intre sesiuni (pe o perioada de timp determinata
de programatorul paginii care creaza cookies). In acest fel se permite spre
exemplu pastrarea informatiilor de conectare (nume utilizator/parola) pentru a
evita citirea lor la fiecare pornire a navigatorului si conectare la site, sau
pastrarea informatiilor despre preferintele utilizatorului, astfel incat sa i se
afiseze direct o pagina personalizata ori de cate ori se conecteaza la site.
Cookies sunt entitati de tipul "nume = valoare" retinute pe partea de client. In
plus ele au asociata o adresa URL prin care navigatorul determina daca un
anumit cookie trebuie sau nu trimis serverului accesat in acel moment.
Exista o serie de limitari care previn abuzul la folosirea de cookies. Un navigator
este restrictionat la cel mult 300 de cookies. In plus nu sunt acceptate mai mult
de 20 de cookies de la acelasi server. Daca o aplicatie necesita mai multe date,
acestea pot fi retinute pe partea de server (prin sesiuni sau stocate in fisiere
sau baze de date).

Observatie: In general exista o perceptie gresita potrivit careia entitatile


cookies ar fi periculoase pentru clienti. Acest lucru este total neadevarat.
135

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.

Cap 5.2.1.1. Restrictii legate de cookies


Pe langa nume si valoarea retinuta, un cookies are asociate o serie de informatii
de restrictionare. Acestea sunt:
l
l
l
l

Data expirarii (ex. 03/12/2003, 14:30:00)


Informatii despre calea valida (ex. /php/client1 )
Informatii despre domeniul valid (ex. serverfirma.ro )
Un parametru referitor la transmiterea securizata

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.

Cap 5.2.1.2. Utilizare cookies in PHP


Suportul pentru cookies este integrat in limbajul PHP. Utilizarea de cookies din
PHP este la fel de facila ca si utilizarea informatiilor din form-uri HTML.
Pentru crearea unui cookie se va folosi functia setcookie . Cea mai simpla forma
a acestei comenzi este:
boolean setcookie("numeCookie", "valoare")
Acest apel va crea un cookie avand numele "numeCookie" si valoarea
specificata. Parametrii de restrictionare vor fi setati toti cu valori implicite.

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.

Cap 5.2.1.3. Probleme la folosirea cookies


Cea mai comuna problema se refera la apelul setcookie dupa ce s-a inceput
trimiterea de informatii in pagina client. In acest caz se va primi un mesaj de
atentionare care explica faptul ca antetul paginii a fost deja trimis si deci
setcookie nu mai are efect.
A doua problema este aceea de a considera ca un cookie este valid in pagina in
care a fost creat.
138

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

Cap 5.2.2. Probleme de securitate la site-urile


PHP
Deseori problema securitatii unui nou site de Web este pusa pe plan secund la
crearea lui. Acest lucru se datoreaza faptului ca securitatea este putin vizibila
unui client si nu are impact imediat asupra percetiei despre site. Din pacate,
lipsa securitatii este foarte vizibila si poate avea consecinte dezastruase pentru
afacere. Care client mai are curajul sa ofere informatii despre cartea sa de
credit unui site despre care afla ca a fost "spart" de catre hackeri.
Un alt aspect se refera la mentinerea securitatii. Chiar daca un site a fost
proiectat cu un grad satisfacator de securitate, datorita evolutiei continue a
domeniului informaticii, continuu se descopera noi brese de securitate si apar
noi metode de inchidere a lor. Din aceasta cauza, la fel de importanta ca si o
proiectare corespunzatoare este mentinerea la zi a securitatii unui site.
Deoarece problema securitatii este foarte vasta, in continuare vor fi trecute in
revista doar cateva aspecte foarte importante. Pentru mai multe informatii se
recomanda studierea unor publicatii dedicate acestui subiect. Un punct de
plecare util este spre exemplu pagina CERT (Computer Emergency Response
Team) www.cert.org.

Cap 5.2.2.1. Securitatea serverului de Web


Prima masura de securitate la nivelul serverului de Web este aceea a revizuirii
instalarii la zi. Acest lucru se poate face usor pentru ca, indiferent de serverul
folosit, firma producatoare ofera continuu versiuni noi si patch-uri. Majoritatea
versiunilor noi se refera la acoperirea unor lacune de securitate descoperite la
versiunea precedenta.
Pe langa aceasta, restul metodelor sunt specifice fiecarui server in parte desi,
principial, sunt asemanatoare. Exemplele urmatoare se refera la serverul de
Apache.
l

Permisiunile pentru directorul ServerRoot

Directorul ServerRoot este directorul in care serverul Apache este instalat. Pe


acest director trebuie sa aibe drepturi doar administratorul serverului. In caz
contrar, un utilizator rau intentionat sau in necunostinta de cauza va putea
schimba optiunile serverului, provocand blocarea acestuia sau va putea copia
informatii secrete. Singure directoare in care utilizatorul sub care ruleaza
serverul trebuie sa aiba drepturi de speciale este directorul LOG in care se scriu
fisierele jurnal si directorul DocumetRoot in care se gasesc paginile site-urilor
gazduite.
l

Protejarea sistemului de fisiere de pe server

O grija speciala trebuie avuta pentru a nu permite utilizatorilor serverului Web


sa acceseze directoare in afara DocumentRoot. Acest lucru se poate asigura
140

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

Permiterea executiei programelor CGI doar din anumite directoare

O cale comuna de a introduce brese in securitate este cea a executiei de


programe prin interfata CGI (Common Gateway Interface). La configurarea
serverului de Web se pot preciza directoarele din care se permite executia unor
astfel de programe. Acestea vor trebui protejate, prin intermediul sistemului de
operare, astfel incat doar anumiti utilizatori sa aiba drepturi de scriere in ele. In
mod obisnuit, dreptul de a gazdui programe executabile prin CGI il are doar
directorul cgi-bin din directorul in care s-a instalat serverul Web.
ScriptAlias /cgi-bin "/usr/local/apache/cgi -bin"
<Directory "/usr/local/apache/cgi-bin">
AllowOverride None
Options None
Order allow, deny
Allow from all
</Directory>

Cap 5.2.2.2. Securitatea instalarii PHP


Cea mai recomandata instalare a interpretorului de PHP este sub forma de
modul incarcabil pe server. Instalarea ca si program CGI este mai instabila si
mai greu de securizat.
Optiunile de configurare se gases in fisierul php.ini.
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.

Cap 5.2.3. Gestiunea utilizatorilor in PHP


In multe aplicatii PHP este nevoie de gestiunea utilizatorilor. Fie ca este vorba
de un forum de discutii la care utilizatorii trebuie sa se inscrie pentru a putea
purta discutii sau de un magazin virtual in care un utilizator are posibilitatea sa
faca cumparaturi on -line, gestiunea utilizatorilor va asigura, pe langa
autentificarea utilizatorilor autorizati si personalizarea aspectului paginilor
afisate respectiv acordarea de drepturi diferite referitor la operatiile care se pot
efectua pe site.
Metodele de a asigura gestiunea utilizatorilor si, implicit, autentificarea acestora
difera destul de mult functie de cerintele aplicatiei. O cerinta importanta este
nivelul de securitate. In mod evident lucrurile sunt mai stricte pentru un site
care asigura tranzactii pe baza informatiilor de pe carti de credit si mai putin
complicate pentru un forum de discutii. O alta cerinta se refera la numarul
utilizatorilor care trebuie identificati pe un site. Daca numarul acestora este
relativ mic, spre exemplu la un grup de discutii in interiorul unui departament al
unei companii, gestiunea acestora se face relativ usor direct din PHP. In cazul
general, in care utilizatorii se pot inregistra pe Web, numarul lor fiind practic
imposibil de estimat exact la proiectarea acelui site, se impune folosirea unei
baze de date din care, prin PHP se pot obtine pe langa informatiile de
autentificare si informatii referitoare la optiunile personale ale fiecaruia. Spre
exemplu, un magazin virtual de interes general, poate afisa pe pagina principala
diferite oferte speciale funtie de varsta utilizatorului autentificat.

Cap 5.2.3.1. Autentificarea utilizand serverul de Web


Un mod simplu si standard de a autentifica utilizatorii este cel pus la dispozitie
chiar de serverul de Web. Acest mod de autentificare este disponibil pentru
orice pagina de Web, nu neaparat scrisa in PHP. In PHP se pot insa obtine si
informatiile de autentificare (nume utilizator si parola) si, ca atare se pot
personaliza paginile pe baza acestor informatii.
In continuare se va prezenta sintaxa serverului Apache pentru autentificare,
celelalte servere punand la dispozitie metode asemanatoare.

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.

Cap 5.2.3.2. Autentificarea folosind PHP


Desi autentificarea prin serverul de Web este simplu de realizat, ea are o serie
143

ABD
de inconveniente cum ar fi:
l

l
l

nu se poate realiza operatia de log-out (parola ramane activa pana la


inchiderea navigatorului). In acest fel, daca se lasa navigatorul pornit,
chiar daca nu mai sunt incarcate paginile secrete, oricine poate sa le
consulte ulterior
autentificarea nu poate expira daca nu se acceseaza serverul un anumit
timp. Daca navigatorul se lasa pornit, autentificarea ramane valabila si
peste cateva zile
nu se poate imbunatatii in nici un fel decat o data cu schimbarea serverului
de Web.
nu poate retine informatii personale pe langa nume si parola.
utilizatorii si parolele trebuie create de catre administratror. Nu se poate
recurge la un sistem automat de inregistrare.

Pentru a realiza autentificarea din PHP se pot utiliza o variatate de metode.


Majoritatea combina variabilele de sesiune sau variabilele cookies cu
interogarea unei baze de date de utilizatori.
Daca in schimb trebuie protejata o singura pagina pentru un singur utilizator se
poate apela la secveta simpla:
Creati fisierul a5232.php pentru a proteja o pagina secreta.

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.

In cazul general se apeleaza la o pagina de inregistrare in care un nou utilizator


va introduce informatiile necesare, inclusiv parola dorita, acestea fiind
inregistrate intr-o baza de date.
Urmatorul exeplu va crea un mic site care asigura atat faza de inregistrare cat
si cea de log-in, autentificare si afisare de informatii personalizate.
Consideram baza de date pentru pastrarea datelor despre utilizatori:
CREATE DATABASE Aplicatia;
USE Aplicatia
CREATE TABLE Utilizatori (
user char(16) PRIMARY KEY,
parola char(16) NOT NULL,
email char(64),
telefon char(24)
);
GRANT all ON Aplicatia.* TO portar@localhost IDENTIFIED BY 'control!';
In acest caz paginile de inregistrare a unui nou utilizator ar putea fi:
<!-- pagina inreg.html -->
<HTML><HEAD><TITLE>Inregistrare</TITLE></HEAD>
<BODY>
<H1>Inregistrare utilizator nou</H1>
<P><HR><P>
<FORM action="inreg.php" method="POST" >
<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>E-mail:</TD>
<TD><INPUT type="TEXT" name="email">
</TD></TR>
<TR><TD>Telefon:</TD>
<TD> <INPUT type="TEXT" name="telefon">
</TD></TR>
<TR><TD> <INPUT type="SUBMIT" value="Aplic"></TD>
<TD> <INPUT type="RESET" value="Reset">
</TD></TR>

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

informatiile despre utilizator pot fi mult mai numeroase


se pot adauga functii JavaScript prin care sa se valideze adresa de e-mail
si numarul de telefon in pagina inreg.html
pentru a evita problemele care apar datorita diferentelor de ora
inregistrate intre calculatoarele client si server se poate adauga un camp
ascuns in fisierul login.html care sa fie completat cu ora clientului. In felul
acesta pagina login.php poate calcula timpul de expirare a informatiilor
cookies functie de timpul real al clientului, evitand probleme la conectare
datorita setarii unor cookies gata expirate.
trebuie testat in pagina de login faptul ca navigatorul accepta sau nu
cookies.

Cap 5.2.4. Tema 5.b


A) Efectuati exemplul si activitatile prezentate in acest capitol.
B) Creati un mic site adaugand la pagina tip catalog de produse (din tema 5.a)
pagini pentru autentificare si inregistrare clienti. In acest scop adaugati o tabela
de utilizatori la baza de date deja creata.
Raspunsul la aceasta tema va consta in prezentarea manierei in care s-a
148

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

'2010 conf. ing. Dan Pescaru

150