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.
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.
l 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.
l 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.
l Este fiabil.
Asigura o buna protectie a datelor prin mecanisme specifice.
l 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.
l Bazat pe fire de executie nucleu.

5
ABD

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


l Suport pentru multe limbaje de programare.
Interfete pentru clienti: C, C++, Eiffel, Java, Perl, PHP, Python.
l 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.
l Securitate ridicata.
Utilizeaza parole criptate.
l 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 mysqld - cu suport de depanare si alocare automata de memorie


l 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

8
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 câteva definitii a termenilor folositi de algebra relationala.

Constituantii (câmpuri, 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 ;

9
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 N-upletii din relatie nu sunt ordonati.


l Ordinea valorilor în N-upleti este data de ordinea definirii atributelor în
modelul relatiei.
l Valorile atributelor din N-upleti sunt atomice. Un atribut nu poate avea valori
multiple. Sunt permise în schimb valori nule.
l 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 stergând 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 încât 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 constrângeri 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 constrângere 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 constrângerile formei anterioare la
care adauga noi conditii.

Forma normala 1 (1NF) cere:

l domeniul atributelor sa cuprinda valori atomice; se interzic câmpurile

11
ABD

compuse sau "relatii în relatie"


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

Forma normala 2 (2NF) cere:

l relatia sa fie în 1NF


l 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 relatia sa fie în 2NF


l 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 este complet dependent functional de orice cheie din R


l 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 A nu determina univoc pe B si C (A |-> B si A |-> C)


l A conduce la valori multiple a lui B
l A conduce la valori multiple a lui C
l B 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 încât 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.
l Viteza de cautare a informatiilor - este un factor esential care poate cere
chiar incalcarea unor forme normale, prin repetarea datelor in tabele.
l 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 Descrierea scopului bazei de date si utilizarii acesteia.


l Referiri la aspecte precum: dimensiunea prevazuta a diverselor tabele,
fisiere index necesare etc.
l Descrierea detaliata a fiecarei tabele, incluzand toate campurile, tipul
acestora, comentarii privind utilitatea etc.
l 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 Tip Constrangeri Comentarii

13
BD

buletin caracter(8) cheie primara numarul de buletin (cu tot cu serie)


nume caracter(24) necesar (not null) numele de familie
prenume caracter(32) necesar (not null) prenumele
data_n data data nasterii

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.
l -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.
l -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 ';'.
l 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 UNSIGNED - permite memorarea doar a valorilor pozitive.


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

18
ABD

lungimea de afisare (ex. 0003)


l 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]


Numar intreg foarte mic. Intervalul de valori posibile este [-128..127]. Daca
se specifica UNSIGNED intervalul este [0..255].
2. SMALLINT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg mic. Intervalul de valori posibile este [-32768..32767]. Daca se
specifica UNSIGNED intervalul este [0...65535].
3. MEDIUMINT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg mediu. Intervalul de valori posibile este [-8388608..8388607].
Daca se specifica UNSIGNED intervalul este [0..16777215].
4. INT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg normal. Intervalul de valori posibile este [-
2147483648..2147483647]. Daca se specifica UNSIGNED intervalul este
[0..4294967295].
5. INTEGER [(M)] [UNSIGNED] [ZEROFILL]
Sinonim cu INT.
6. BIGINT [(M)] [UNSIGNED] [ZEROFILL]
Numar intreg mare. Intervalul de valori posibile este [-
9223372036854775808..9223372036854775807]! Daca se specifica
UNSIGNED intervalul este [0..18446744073709551615].
7. 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.175494351E-
38..3.402823466E+38].
8. 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].
9. REAL [(M, D) [ZEROFILL]
Sinonim cu DOUBLE.
10. 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.
11. NUMERIC [(M [, D]) [ZEROFILL]
Sinonim cu DECIMAL.

1.2. Tipuri de date data calendaristica si timp

19
ABD

1. DATE
Data calendaristica. Intervalul de valori posibile este ['1000-01-01'..'9999-
12-31']. Stocarea/afisarea se face implicit in formatul 'YYYY-MM-DD' (an-
luna-zi).
2. 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).
3. 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.
4. 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.
5. 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..00-
69).

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 Constantele tip sir de caractere se includ intre apostroafe sau ghilimele:

21
ABD

'constnta sir'
"alta constanta sir"
In interiorul unui sir se pot include caractere speciale precedate de semnul
'\' (escape):
¡ \n Trecere la linie noua (new line).

¡ \t Tab (caracter de aliniere).

¡ \r Salt la inceputul liniei (carriage return).

¡ \b Sterge inapoi.

¡ \' Caracterul '.

¡ \" Caracterul ".

¡ \\ Caracterul \.

¡ \% Caracterul '%'. Se poate folosi pentru a cauta caracterul %, in

conditiile in care acest caracter este folosit in expresii regulate


(subiectul va fi detaliat ulterior).
¡ \_ Caracterul _. Se poate folosi pentru a cauta caracterul _, in conditiile

in care acest caracter este folosit in expresii regulate (subiectul va fi


detaliat ulterior).
Rulati secventele:
Activitate 1
mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello' ;
mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello" ;
l 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
l 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 Lungime maxima Caractere interzise
Baza de date 64 '/'
Tabela 64 '/' si '.'
Coloana 64
Alias 255

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


moduri, functie de contextul existent:
Referinta la coloana Semnificatie

22
ABD

Referinta la coloana unei tabele din baza de date activa. Se


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

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;
l Comentarii pe o singura linie care incep cu -- si continua pana la sfarsitul
liniei. Este necesar cel putin un spatiu dupa semnul --;
l 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

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


Activitate 2
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 + pentru adunare;
l - pentru scadere;
l * pentru inmultire;
l / 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.
l OR
|| - SAU logic. Intoarce 1 daca cel putin un argument nu este 0 sau NULL.
l 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 = egalitate; la compararea cu NULL intoarce NULL;


l <> sau != inegalitate;
l < - mai mic;
l <= - mai mic sau egal;
l > - mai mare;
l >= - mai mare sau egal;
l <=> - echivalenta; la compararea cu NULL intoarce 0 sau 1 (1 doar la NULL
<= > NULL); daca ambii operanzi sunt diferiti de NULLse comporta ca si =;
l IS NULL - testeaza daca operandul are valoarea NULL;
l IS NOT NULL - testeaza daca operandul este diferit de NULL;
l ISNULL(expr) - testeaza daca expresia are valoarea NULL;
l expr BETWEEN min AND max - testeaza daca valoarea expresiei este in
intervalul [min..max];
l expr IN (value,...) - testeaza daca valoarea expresiei este in lista de valori
specificata;
l expr NOT IN (value,...) - testeaza daca valoarea expresiei nu este in lista de
valori specificata;
l 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:

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' ;
Activitate 6 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 ASCII(str) - intoarce codul ASCII al caracterului de pe pozitia 1 din sir. Daca


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

25
ABD

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


l LEFT(str,len) - intoarce un sir format din primele len caractere din sirul dat.
l RIGHT(str,len) - intoarce un sir format din ultimele len caractere din sirul
dat.
l SUBSTRING(str,pos,len)
MID(str,pos,len) - intorc subsirul de pe pozitia pos, de lungime len caractere
din sirul str.
l 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.
l LTRIM(str)
RTRIM(str)
TRIM(str) - intoarce sirul str fara spatiile de la inceput (LTRIM), sfarsit
(RTRIM) sau din ambele parti (TRIM).
l SPACE(N) - intoarce un sir format din N spatii.
l LOWER(str)
UPPER(str) - intorc sirul str cu toate caracterele convertite la litere mici,
respectiv litere mari.
l 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:

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
Activitate 7
('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 ABS(X) - valoarea absoluta (fara semn) a lui x.


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

26
ABD

sus)
l ROUND(X) - rotunjire la cel mai apropiat intreg
l EXP(X) - exponentiala (e la puterea x)
l LOG(X) - logaritm natural din x
l LOG10(X) - logaritm in baza 10 din x
l POW(X,Y) - x la puterea y
l SQRT(X) - radical de ordinul 2 din x
l PI() - numarul PI; implicit se afiseaza cu 5 zecimale dar in calcule intervine
cu dubla precizie
l COS(X), SIN(X),TAN(X) - cosinus, sinus si tangenta de x
l RAND()
RAND(N) - genereaza un numar pseudo-aleator in intervalul [0..1]; prin N se
poate specifica o valoare de initializare calcul
l LEAST(X,Y,...) - intoarce cea mai mica valoare din lista valorilor specificate
l GREATEST(X,Y,...) - intoarce cea mai mare valoare din lista valorilor
specificate

Rulati secventele:

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


mysql> SELECT FLOOR(1.23), CEILING(1.23), ROUND(1.58) ;
Activitate 8
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 DAYOFWEEK(date) - indexul zilei din spatamana al datei specificate


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

Rulati secventele:

27
ABD

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


()) ;
mysql> SELECT DAYNAME(NOW()), MONTHNAME(NOW()), YEAR
Activitate 9 (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 DATABASE() - numele bazei de date active


l USER() - numele utilizatorului coectat la server
l VERSION() - returneaza versiunea serverului MySQL instalat
l 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)
l 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 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.
l IF NOT EXISTS - inhiba mesajul de eroare care se genereaza daca la
incercarea de a crea o tabela care mai exista.
l 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)

28
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 ...)".
l 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:

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,
Activitate 11 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 intr-
un 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:

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


majoritatea implementarilor UNIX aceasta valoare este de 8 caractere.
l Numele utilizatorilor si parolele sunt pastrate separat de mySQL si nu au
nimic in comun cu cele din sistemul de operare.
l 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
Privilegiu Context Semnificatie
coloana
select Select_priv tabele permite selectarea (vizualizarea) datelor
insert Insert_priv tabele permite adaugarea unor noi inregistrari
update Update_priv tabele permite modificarea datelor
delete Delete_priv tabele permite stergerea inregistrarilor
index Index_priv tabele permite crearea/stergerea indecsilor
permite redenumire sau modificarea
alter Alter_priv tabele
structurii tabelei
baza de date, tabele sau
create Create_priv permite crearea unei baze de date/tabele
indecsi
drop Drop_priv baza de date, tabele permite stergerea unei baze de date/tabele
permite delegarea privilegiilor catre alt
grant Grant_priv baza de date, tabele
utilizator
permite oprirea serverului din programul
shutdown Shutdown_priv administrare server
client
permite vizualizarea/oprirea proceselor in
process Process_priv administrare server
executie
permite schimbul de date intre tabele si
file File_priv acces la fisiere externe
fisiere

Cateva dintre aceste privilegii necesita o atentie aparte:

l 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.
l Privilegiul alter poate fi folosit pentru a redenumi tabele, modificand astfel

32
ABD

baza de date si facand astfel inutilizabile programele altor utilizatori.


l Privilegiul file poate fi folosit pentru a citi informatii sensibile de pe server.
l Privilegiul shutdown da posibilitate opririi serverului de la distanta.
l 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:

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


conecta.
l 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 Global - se aplica tuturor bazelor de date existente pe un server


l Database - se aplica tuturor tabelelor dintr-o baza de date
l Table - se aplica tuturor coloanelor dintr-o tabela
l 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:

l 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.
l coloane - o lista de una sau mai multe coloane. Permite stabilirea

33
ABD

privilegiilor la nivel de coloane.


l 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.
l 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.
l 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.
l 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:

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

36
ABD

parametrul este folosit doar cand este cu adevarat necesar.


l 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.
l INTO - este optional, se foloseste pentru compatibilitate cu alte sisteme
SQL. Datorita claritatii mai mari a interogarii se prefera totusi utilizarea lui.
l tbl_nume - specifica numele tabelei unde se adauga inregistrarile.
l (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.
l VALUES - specifica seturile de date (inregistrarile) care se vor adauga in
tabela.
l (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:

l operatia de selectie nu poate contine clauza ORDER_BY pentru ordonarea


rezultatului
l 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 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.
l IGNORE - nu se intrerupe executia in cazul in care se duplica chei unice la
actualizare. Inregistrarile care cauzeaza erori sunt pur si simplu ignorate.
l tbl_nume - nume tabela unde are loc actualizarea
l SETcol_nume1=expr1,col_nume2=expr2,... - indica acele coloane care
sunt modificate si noile lor valori. Expresiile de actualizare pot cuprinde

38
ABD

vechile valori ale campurilor de actualizat.


l 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 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.
l FROMtbl_nume - specifica tabela de unde se sterg inregistrari.
l 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:

l 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.
l HIGH_PRIORITY - da prioritate interogarii curente fata de alte interogari
INSERT sau UPDATE aflate in coada de asteptare pentru acea tabela.
l DISTINCT - Permite eliminarea randurilor duplicate din selectie.

41
ABD

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


specifica nici DISTINCT, nici ALL, implicit se considera ALL.
l 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.
l 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).
l 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.
l 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.
l 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:

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

44
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 COUNT(*) - numara cate inregistrari sunt selectate in fiecare grup.


l COUNT(DISTINCT expr) - numara cate inregistrari pentru care expresia are
o valoare distincta sunt selectate in fiecare grup.
l AVG(expr) - calculeaza media aritmetica a valorilor expresiei pentru
inregistrarile din fiecare grup.
l MIN(expr) - calculeaza valoarea minima a expresiei pentru toate
inregistrarile din fiecare grup.
l MIN(expr) - calculeaza valoarea maxima a expresiei pentru toate
inregistrarile din fiecare grup.
l 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:

l The FreeODBC Pages.

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

l 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 MYSQL - structura care gestioneaza conexiunea cu server-ul.


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

Principalele functii din biblioteca sunt:

l mysql_real_connect() - realizeaza conexiunea cu server-ul

48
ABD

l mysql_close() - inchide conexiunea cu severul


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

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


documentatia de la adresa:

l 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 connect - realizeaza conexiunea cu server-ul MySQL


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

Informatii detaliate despre interfata DBI se pot obtine la adresa:

l 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 mysql_connect() - realizeaza o conexiune cu server-ul de baze de date


l mysql_close() - inchide conexiunea
l mysql_db_query() - trimite o comanda SQL catre server
l mysql_affected_rows() - intoarce numarul de inregistrari afectate de
comenzile INSERT, UPDATE sau DELETE
l mysql_num_rows() - numarul de randuri din rezultat
l mysql_fetch_array() - returneaza rezultatul unei interogari sub forma unui
tablou asociativ (coloana-valoare)
l mysql_fetch_object() - returneaza rezultatul sub forma unui obiect care are
ca si atribute campurile din rezultat
l mysql_fetch_row() - returneaza rezultatul sub forma unui tablou
l 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:

l 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 nume_tabela - specifica tabela care va fi blocata


l READ - toti clienti (inclusiv cel care blocheaza) pot doar citi, dar nu si insera
sau modifica datele din tabela
l 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 master-


slave. 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 Se creaza un utilizator pe calculatorul master. Acest utilizator va fi folosit


doar pentru replicare si va avea setat dreptul FILE.
l Se face o copie de siguranta pentru toate tabelele care vor fi replicate.
l Se seteaza optiunea log-bin in fisirul my.cnf de pe master. Pentru a avea
efect se restarteaza calculatorul master.
l Se incarca manual copia de siguranta pe calculatorul slave.
l 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.

l 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 mecanisme de autentificatre utilizatori


l sisteme de gestiune a continutului
l sisteme de tip "web based e-mail"
l gestionare de liste de mesaje
l forumuri Web
l 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 performanta buna
l interfete cu variate sisteme de gestiune a bazelor de date
l biblioteci puternice care acopera toate operatiilor Web uzuale
l cost scazut
l usor de invatat si utilizat
l portabil
l 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 pre-
compilat si se poate instala direct (ex. apache_1.3.31-win32-x86-
no_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 sub-


directorul "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 host-
name-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 Se va aduce ultima versiune (recomandat 1.3.x) pentru Linux de la adresa:


http://www.apache.org/dist/httpd/binaries/linux/
l Se decomprima in directorul /usr/local/apache si apoi se intra in acest
director.
l Se compileaza distributia prin comanda make
l Se instaleaza cu ajutorul comenzii make install
l Se modifica fisierul /usr/local/apache/conf/httpd.conf conform specificatiei
in cazul instalarii sub Windows
l 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

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


3. Se schimba directorul prin cd /usr/local/php-5.0.x.
4. Se executa comanda de confisurare: ./configure --with-xml --with-
apache=../apache_1.3.x --with-curl=/usr/local/curl --with-
pspell=/usr/local/pspell.
5. Se compileaza cu ajutorul comenzii make.
6. Se instaleaza prin comnada make install.
7. Se copiaza fisierul de initializare in directorul lib prin cp
php.ini.dist /usr/local/lib/php.ini.
8. 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
9. 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

ftp://ftp.roedu.net/pub/mirrors/ftp.mysql.com/Downloads/MySQL -
4.0/mysql-4.0.21-win.zip.
2. Dezarhivare fisier mysql-4.0.21-win.zip intr-un director temporar (ex
c:\temp).
3. Se va rula programul setup.exe din directorul de dezarhivare. Directorul
de instalare va fi ales C:\mysql.
4. 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 .
5. 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
6. 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. Inserarea codului PHP intr-o pagina HTML. Taguri PHP


2.1.2. Generarea dinamica de continut HTML
2.1.3. Tipuri de date. Conversii de tip
2.1.4. Identificatori. Constante
2.1.5. Variabile utilizator. Variabile referinta. Domeniu de valabilitate
2.1.6. 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.

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

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

l 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.
l stilul C++: Comentariul se intinde pe o singura linie, de la aparitia
semnului '//' pana la sfarsitul liniei curente.
l 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:

<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
Ex. 1 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 Integer - utilizat pentru numere intregi


l Double - utilizat pentru numere reale
l String - utilizat pentru siruri de caractere
l Array - utilizat pentru a stoca date multile de acelasi tip
l 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 Identificatorii pot fi de orice lungime si pot fi formati din litere, cifre, liniuta
de subliniere sau semnul dolar.
l Identificatorii nu pot incepe cu o cifra.
l 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 constantele intregi: 0, 100, -1320


l constantele de tip double: 0.00, 3.1523, -4.5
l 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.
l Locale unei functii - variabilele create in functii sunt vizibile doar in
interiorul acestora.
l 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:

<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"];
Ex. 2 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 Exemplu


+ adunare $a + $b
- scadere $a - $b
* inmultire $a * $b
/ impartire $a / $b
% modulo $a % $b
++ incrementare - post $a++
++ incrementare - pre ++$a
-- decrementare - post $a--
-- decrementare - pre --$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:

<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>";
Ex. 1 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 Echivalent cu


+= $a += $b $a = $a + $b
-= $a -= $b $a = $a - $b
*= $a *= $b $a = $a * $b
/= $a /= $b $a = $a / $b
%= $a %= $b $a = $a % $b
.= $s1 .= $s2 $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 Exemplu


== egalitate $a == $b
=== test de identitate $a === $b
!= inegalitate $a != $b
<> inegalitate $a <> $b
< mai mic $a < $b
> mai mare $a > $b
<= mai mic egal $a <= $b
>= mai mare egal $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 Denumire Rezultat


! negare !$a neaga valoarea logica a lui $a
&& si logic $a && $b intoarce adevarat doar daca ambele valori $a si $b sunt adevarate
and si logic $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
|| sau logic este adevarata
$a or $b intoarce adevarat daca cel putin una dintre valorile lui $a sau $b
or sau logic
este adevarata
sau
xor $a xor $b intoarce adevarat daca $a si $b au valori logice diferite
exclusiv

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 Rezultat

71
ABD

~ negare pe biti ~$a inverseaza valorilor tuturor bitilor lui $a


& si pe biti $a &$b doar biti pe 1 in $a si $b simultan sunt setati pe 1 in rezultat
| sau pe biti $a | $b biti pe 1 in $a sau $b sunt setati pe 1 in rezultat
sau exclusiv pe $a ^ $b bitii setati in $a sau $b dar nu in ambele sunt setati pe 1 in
^
biti rezultat
<< deplasare stanga $a << $b deplaseaza bitii din $a la stanga cu $b pozitii
>> deplasare dreapta $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 Asociativitate Operator


1 stanga ,
2 stanga or
3 stanga xor
4 stanga and
5 stanga = += -= *= /= .= %=
6 stanga ?:
7 stanga ||
8 stanga &&
9 stanga |
10 stanga ^
11 stanga &
12 - == != ===
13 - < > <= >=
14 stanga << >>
15 stanga +-.
16 stanga */%
17 dreapta ! ~ ++ -- @
18 dreapta []
19 - new
20 - ()

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:

<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;
Ex. 2
$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

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
Ex. 1 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.

<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>";
Ex. 2 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

82
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 crearea unei sesiuni


l inregistrarea variabilelor sesiune
l utilizarea variabilelor sesiune pentru controlul accesului sau personalizarea

92
ABD

paginii
l 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>

<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>
Ex. 1
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 bool array_key_exists ( tip_oarecare cheie_cautata, array tablou );

96
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>

<?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);
Activitate
echo "<P><HR>Tabloul sortat prin <B>krsort()</B>:<BR>";
1
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 array getdate ( [int timestamp ] );

98
ABD

Functia getdate creaza un tablou asociativ continand informatii despre data


specificata de parametrul optional UNIX timestamp sau, despre data curenta a
serverului daca parametrul lipseste. Tabloul asociativ va avea urmatoarele chei:
"seconds", "minutes", "hours", "mday" (ziua lunii in intervalul 1..31),
"wday" (ziua din saptamana: 0 - duminica .. 6 - sambata), "mon" (luna in
format 1 .. 12), "year" (anul pe 4 cifre), ydey (ziua din an: 1 .. 366),
"weekday" (ziua saptamanii, text in engleza), "month" (luna, text in engleza).

l int 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 Caractere Semnificatie


a 'am' sau 'pm' A 'AM' sau 'PM'
ziua in saptamana pe 3 caractere
d ziua in luna (01..31) D
'Mon' .. 'Sun'
luna, cuvant ('January' ..
F g ora, format 1..12
'December')
G ora, format 0..23 h ora pe 2 caractere, format 01..12
ora pe doua caractere, format
H i minute 00..59
00..23
ziua din saptamana, ('Monday' ..
j ziua in luna 1..31 l
'Sunday')
m luna 01..12 M luna, text pe 3 caractere 'Jan' .. 'Dec'
n luna 1..12 s secunde 00..59
sufixul in engleza pentru ziua
numarul de zile ale lunii curente
S lunii t
28..31
'st', 'nd', 'rd', sau 'th'
ziua saptamanii 0(duminica)..6
w Y anul pe 4 cifre
(sambata)
y anul pe doua cifre z ziua din an 0..365

99
ABD

Creati fisierul a4112.php referitor la functii de prelucrare date


calendaristice.

<HTML>
<HEAD><TITLE>Activitate 4.1.1.2.</TITLE></HEAD>
<BODY>

<?php
$acum = time();
echo "<P>Data curenta (Unix timestamp): ".$acum."<BR>";
Activitate echo "<P>Data curenta (<b>date('\R\u\l\a\\t \a\s\\t\a\z\i, d F Y
2 \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 Valoare Semnificatie


M_PI 3.14159265358979323846 numarul PI
M_E 2.7182818284590452354 numarul e
M_LOG2E 1.4426950408889634074 log in baza 2 din e
M_LN2 0.69314718055994530942 ln(2)
M_SQRT2 1.41421356237309504880 Radical din 2
M_EULER 0.57721566490153286061 contanta lui Euler

l 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 float cos ( float unghi );


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

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

l float deg2rad ( float unghi );


l 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 tip_n max ( tip_n numar1, tip_n nuamar2, ...);


l 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 int mt_rand ( [[int min,] int max] );

101
ABD

Functia mt_rand genereaza un numar aleator. Valoarea generata va fi in


intervalul [0..mt_getrandmax()] daca min si max lipsesc, in intervalul [0..max]
daca min lipseste, respectiv in intervalul [min..max] daca ambii parametrii sunt
prezenti.

l 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>

<?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
Activitate
($noteExamene)." <BR>";
3
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 string ltrim ( string sir );


l string rtrim ( string sir );
l 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 void printf ( string format, tip_oarecare valoare1 ... );


l 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 Caracter Semnificatie


argumentul este considerat ca intreg
%b intreg reprezentat binar %c si transformat in caracterul ASCII
corespunzatoare valorii sale
%d intreg cu semn reprezentat binar %u intreg fara semn reprezentat binar
%f numar in virgula flotanta %o intreg reprezentat octal
%s sir de caractere %X intreg reprezentat hexazecimal

l string strstr ( string sirOriginal, string sirCautat );


l 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 string ucfirst ( string sir );


l 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 string strtolower ( string sir );


l 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>

<?php
$sir = "alin dinu george ion laurentiu ovidiu serban";
Activitate $adresa = "cineva@servermail.ro";
4
$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, "@");

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

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


if ( $fp === false )
$fp = fopen ( "counter.dat", "w" );
$n = fgets ( $fp );
Activitate
$n = $n+1;
5
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 e-
mail 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.
l 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.
l 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.
l este rapid.
In multe aplicatii este chiar mai rapid dacat alte sisteme foarte scumpe.
l este fiabil.
Asigura o buna protectie a datelor prin mecanisme specifice.
l asigura suport pentru multe limbaje de programare.
Interfete pentru clienti: C, C++, Eiffel, Java, Perl, PHP, Python
l 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:

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,
Activitate mysql> nume char(64) NOT NULL,
1 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 Fisierele de mari dimensiuni sunt parcurse extrem de incet

115
ABD

l Cautarea unei informatii in fisier necesita un timp mare si diverse artificii de programare
l Apar probleme la accesul concurent asupra fisierelor care pot ingreuna sau chiar bloca pentru
un timp indelungat accesul la site
l La stergerea sau inserarea datelor in mijlocul fisierului acesta va trebui recopiat, ceea ce duce
la timpi inadmisibili de mari pentru prelucrari
l 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:

<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"] ) );
Activitate
$telEdi = addslashes ( trim ( $HTTP_POST_VARS["telEdi"] ) );
2
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:

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,
Activitate mysql> nume char(64) NOT NULL,
1 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 Fisierele de mari dimensiuni sunt parcurse extrem de incet

123
ABD

l Cautarea unei informatii in fisier necesita un timp mare si diverse artificii de programare
l Apar probleme la accesul concurent asupra fisierelor care pot ingreuna sau chiar bloca pentru
un timp indelungat accesul la site
l La stergerea sau inserarea datelor in mijlocul fisierului acesta va trebui recopiat, ceea ce duce
la timpi inadmisibili de mari pentru prelucrari
l 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:

<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"] ) );
Activitate
$telEdi = addslashes ( trim ( $HTTP_POST_VARS["telEdi"] ) );
2
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 probleme legate de oferirea informatiilor cu adevarat importante


l probleme referitoare la nivelul prezentarii, functie de segmentul de
populatie vizat
l probleme legate de interactivitate
l probleme legate de actualizarea informatiilor
l 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.

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


Activitate ofera servicii comerciale.
1
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 Crackeri
l Riscul unui impact minor pe piata
l Caderi hardware
l Erori software
l Probleme cu liniile de comunicatii
l Neclaritati in legislatie
l 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 e-


comerce 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 Data expirarii (ex. 03/12/2003, 14:30:00)


l Informatii despre calea valida (ex. /php/client1 )
l Informatii despre domeniul valid (ex. serverfirma.ro )
l 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.

<?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>";
Activitate echo "<HEAD>";
1 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 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.
l 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.
l register_globals
Daca aceasta optiune este ON, toate datele care provin din exterior (din

141
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.).
l 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 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
l autentificarea nu poate expira daca nu se acceseaza serverul un anumit
timp. Daca navigatorul se lasa pornit, autentificarea ramane valabila si
peste cateva zile
l nu se poate imbunatatii in nici un fel decat o data cu schimbarea serverului
de Web.
l nu poate retine informatii personale pe langa nume si parola.
l 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.

<?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>
Activitate <TR><TD><CENTER>Parola:
2 <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!";
}
?>

144
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 informatiile despre utilizator pot fi mult mai numeroase


l se pot adauga functii JavaScript prin care sa se valideze adresa de e-mail
si numarul de telefon in pagina inreg.html
l 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.
l 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

S-ar putea să vă placă și