Sunteți pe pagina 1din 133

AF

Dezvoltare web cu PHP

Pentru nceptorii n programare i n PHP care vor s devin profesioniti

DR

Autor: Flavius Aspra

21 iulie 2012

O iniiativ Yet Another Project


Homepage: http://yet-another-project.github.com/

Dezvoltare web cu PHP


Pentru nceptorii n programare i n PHP care vor s devin profesioniti
Flavius Aspra
Copyright 2010-2012, Flavius Aspra.
Toate drepturile rezervate lui Flavius Aspra.
Nicio parte din acest lucrare nu poate repus ctre descrcare electronic fr acordul autorului.
Redistribuirea sa n format printat este admis, atta timp ct distribuitorul nu are niciun fel de ctiguri
nanciare de pe urma acestei activiti sau a altor activiti conexe.
Redistribuirea sa, de orice natur ar ea, trebuie s se fac integral i fr modicri aduse lucrrii.
Flavius Aspra, <avius@php.net>
URL: http://flavius.github.com/

Cuprins

Introducere
Scopul acestei cri . . . . . . . . .
De ce am nevoie? Premize . . . . .
Convenii folosite . . . . . . . . . .
Cum s nvei ecient programare
Comunitatea . . . . . . . . .
Exerciiile . . . . . . . . . . .
Cum pot ajuta? . . . . . . . . . . .
O privire de ansamblu a capitolelor

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

1 Reelistic
1.1 Noduri, TCP/IP, reele . . . . . .
1.2 Domenii . . . . . . . . . . . . . . .
1.3 Protocoale . . . . . . . . . . . . . .
1.3.1 Primul exerciiu de hacking
1.4 Instalarea mediului de dezvoltare .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

2 Controlul uxului de execuie i de date


2.1 O altfel de remprosptare . . . . . . . . . .
2.2 Output simplu . . . . . . . . . . . . . . . .
2.3 Folosirea variabilelor . . . . . . . . . . . . .
2.3.1 Variabile i tipuri de date elementare
2.3.2 Operaii cu string, int, oat . . . . .
2.3.3 Operaii matematice . . . . . . . . .
2.4 Algoritmi i scheme logice . . . . . . . . . .
2.5 Tipul de date boolean. Expresii logice . . .
2.5.1 Conjuncii, disjuncii i negaii . . .
2.6 Condiii if i switch . . . . . . . . . . . . .
2.7 Buclele while i do while . . . . . . . . . . .
2.7.1 break i continue . . . . . . . . . . .
2.8 Tipul de date array. Bucla foreach . . . . .
2.9 Bucla for . . . . . . . . . . . . . . . . . . .
2.10 Completri . . . . . . . . . . . . . . . . . .
2.10.1 Stringuri . . . . . . . . . . . . . . .
2.10.2 Constante i alte tipuri de date . . .
2.10.3 Ali operatori . . . . . . . . . . . . .
2.10.4 Sfaturi de stil . . . . . . . . . . . . .
2.10.5 Breaking down the logic . . . . . . .
3

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

6
6
7
7
9
10
10
11
11

.
.
.
.
.

13
13
15
16
17
20

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

28
28
32
33
35
36
38
41
44
46
47
51
54
55
60
61
61
63
65
66
67

Dezvoltare web cu PHP


2.10.6 Coding convention . . . . . . . . . . .
2.11 Input i formulare . . . . . . . . . . . . . . .
2.11.1 Formulare, business logic i view logic
2.12 Array-uri multidimensionale . . . . . . . . . .
2.12.1 Geometria i normalizarea array-urilor
2.13 Sisteme de numeraie . . . . . . . . . . . . . .
2.13.1 Baze numerice . . . . . . . . . . . . .
2.13.2 Operaii pe bii . . . . . . . . . . . . .
2.14 Variabile variabile . . . . . . . . . . . . . . .
2.15 Referine . . . . . . . . . . . . . . . . . . . . .
2.16 Exerciii . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

69
70
72
74
76
77
77
78
80
81
81

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

84
84
84
91
95
96
97
98
98
99
100
101
103
104
104
105
108
109
110
111
116
118
120
121
122
124
124
125

4 Baze de date i lucrul n echip


4.1 Git . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Istoria unui proiect . . . . . . . . . . .
4.1.2 Getting started . . . . . . . . . . . . .
4.2 Baze de date relaionale . . . . . . . . . . . .
4.3 Comunicarea cu MySQL din runtime-ul PHP
4.4 Designul bazelor de date . . . . . . . . . . . .
4.4.1 Database Normalization . . . . . . . .
4.5 Debugging and proling . . . . . . . . . . . .
4.6 Lucrul n echip . . . . . . . . . . . . . . . .
4.6.1 Norme de comunicare . . . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

127
127
127
128
128
130
131
133
133
133
133

3 Reutilizarea i modularizarea codului


3.1 Funcii . . . . . . . . . . . . . . . . . . . .
3.1.1 Funcii proprii. Termeni generali .
3.1.2 Cnd s introducem funcii noi . .
3.1.3 Funcii variabile . . . . . . . . . .
3.1.4 Closures . . . . . . . . . . . . . . .
3.1.5 Default values . . . . . . . . . . . .
3.2 Debugging . . . . . . . . . . . . . . . . . .
3.3 Folosirea manualului . . . . . . . . . . . .
3.3.1 Site-ul ocial php.net . . . . . . .
3.3.2 Studiu de caz: funcii variadice . .
3.3.3 Categoriile de extensii disponibile .
3.3.4 Extensii de baz . . . . . . . . . .
3.4 Structuri de date . . . . . . . . . . . . . .
3.4.1 Stack i queue . . . . . . . . . . .
3.4.2 Structuri de date recursive . . . .
3.5 Call Stack . . . . . . . . . . . . . . . . . .
3.6 Fiiere multiple . . . . . . . . . . . . . . .
3.6.1 abloane . . . . . . . . . . . . . . .
3.6.2 Primul site complet . . . . . . . .
3.7 Directorul curent de lucru . . . . . . . . .
3.8 Formulare II. File uploads . . . . . . . . .
3.9 Lucrul cu iere . . . . . . . . . . . . . . .
3.9.1 Filesystems . . . . . . . . . . . . .
3.10 Cookies, sesiuni, autenticare . . . . . . .
3.10.1 Sessions . . . . . . . . . . . . . . .
3.10.2 Authentication . . . . . . . . . . .
3.11 Felicitri . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Dezvoltare web cu PHP


4.6.2

Norme comportamentale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Introducere
Acest capitol conine informaii foarte importante despre cum s studiezi, unde s ceri ajutor, cum
s raportezi greeli i n general cum s proi la maxim de materialul prezentat. Recomand citirea sa cu
atenie.

n ultimii ani, utilizarea Internetului a crescut rapid. Numrul de dispozitive conectate la Internet
crete n mod exponenial de la an la an, iar web-ul1 a devenit scena principal. Web-ul nu mai este
static demult, avem reele sociale,2 feed-uri,3 bloguri i microbloguri,4 .a.m.d. Observm cum mai toate
activitile noastre informaionale s-au mutat pe web.
ns aceste activiti devin din ce n ce mai complexe, la fel ca i aplicaiile5 care le susin. Iar aceste
aplicaii trebuie dezvoltate de cineva de programatori.
PHP este unul dintre cele mai folosite limbaje pentru crearea de aplicaii web dinamice. Succesul su
se datoreaz n special simplitii sale, ns acest lucru are dou tiuri: pe de o parte este uor accesibil,
pe de cealalt parte poi face foarte uor greeli majore.

Scopul acestei cri


Pentru a scrie aplicaii PHP bune6 este cerut simul critic al programatorului, ns exist o mare
problem: nceptorul care alege PHP ca primul su limbaj de programare nu are un sim critic dezvoltat
sau gndirea analitic necesare n programare. n combinaie cu accesibilitatea aparent a limbajului
PHP, acest lucru se dovedete fatal pe termen lung.
Scopul acestei cri este s dezvolte cititorului att gndirea autonom, productiv, critic, ct i
capacitatea de analiz i sintez, capaciti att de vitale n programare.
Lucrarea de fa nu este nici pe departe complet nici nu vrea s e. Tot ceea ce vrea este s-i ofere
cititorului o fundaie bun de start. Acest lucru se face punnd accent pe terminologie i pe explicarea
modului de funcionare a noiunilor i tehnologiilor prezentate.
Dup cum probabil intuieti deja, scopul acestei cri este de a susine cursantul s devin bun n
perspectiv, ind orientat spre viitor, pe termen lung, i nu pe satisfacii de moment.
1

World Wide Web


hi5, facebook, lastFM, delicious
3
RSS, Atom
4
twitter
5
Termenul aplicaie nu este tocmai corect, n sensul tradiional, ns autorul consider c limba este ceva maleabil,
care se schimb n timp n funcie de nevoi.
6
performante, sigure, complexe, mentenabile
2

Dezvoltare web cu PHP

De ce am nevoie? Premize
Aceast lucrare pleac de la premiza c cititorul tie deja (X)HTML,7 eventual i CSS, dar acesta
din urm nu este necesar pentru nelegerea lucrurilor prezentate sau pentru nvarea PHP. Ar trebui
studiat oricum, cci fr el nu este posibil design-ul de website-uri aspectuoase.
Acolo unde va nevoie, vor prezentate i noiunile JavaScript8 necesare.
Un lucru important de care cititorul are nevoie este rbdare. Citete cu atenie i ncearc s nelegi
tot, cci informaia este comprimat i uneori pare s nu aib nicio aplicabilitate practic, ns e doar o
iluzie tot ce scrie n acest ghid scurt este important. Nu uita c acest curs se rezum doar la fundaie,
la cunotinele de baz.
Aa cum spune i coperta acestei cri, se pleac de la premiza c cititorul vrea s devin profesionist
n PHP. Dac nu asta este intenia sa, atunci lucrarea de fa nu este potrivit.
Cartea de fa nu este potrivit nici dac ai o problem concret de programare i te atepi s
gseti o soluie, n special dac eti nceptor. Un nceptor ar trebui s i canalizeze energia ncercnd
s neleag noiunile expuse. n acest fel se economisete mai mult timp i frustrare pe termen lung.
Dup parcurgerea crii, i vei da seama c rezolvarea problemei tale imediate este n fapt marginal
carierei tale de programator profesionist.

Ca un viitor profesionist, citete cu atenie acest material, i ncearc s nelegi nu numai


conceptele de care te loveti, ci i implicaiile lor. Analizeaz-le, att pe el nsele, ct i n
relaie cu celelalte concepte introduse. Cu ct sintetizezi mai mult atunci cnd ntlneti ceva
nou, cu att vei ajunge s jonglezi cu noiunile nvate mai rapid, lucru care i va permite s
i inovativ.
De exemplu, n primul capitol vei nva despre reelistic. ntreab-te pe parcursul ntregii
cri ce efecte au limitrile HTTP asupra posibilitilor sau asupra securitii.

Un alt lucru de care ai nevoie este stpnirea limbii romne. Experienele noastre cu cursanii ne-au
nvat c muli dintre cei ce aspir a programatori nu ndeplinesc aceast premiz. Unii dintre ei au
avut diculti nu pentru c nu ar ti s vorbeasc, ci pentru c nu au realizat intensitatea cu care punem
accent pe acest aspect. Nu te teme, prima faz de tutelare9 are exact acest scop: s te aduc pe linia de
plutire.
i nu n ultimul rnd, este nevoie de stpnirea relativ bun a limbii engleze. Fr ea oricum nu ai
avea succes n programare de multe ori va trebui s citeti documentaii n englez, ba mai bine, s i
documentezi aplicaiile n englez. Apropo de documentaie, toate proiectele de succes au o documentaie
bun n englez. Nu te impacienta dac nu te simi pregtit s scrii ceva n englez, pn la capitolul 3
inclusiv vei avea ansa s i mbunteti engleza doar citind.

Convenii folosite
Pentru a face lectura ct mai plcut, cartea de fa respect anumite convenii, att de natur
tipograc, ct i inerente comunitii din jurul ei.
n primul rnd, pe prima pagin se a un link ctre pagina de start a proiectului. Aceast pagin
va numit mereu pagina phpro. Urmtoarea seciune i va descrie despre ce este vorba n detaliu.
n al doilea rnd, cnd spun wikipedia, m refer la versiunea original n englez a site-ului http:
//en.wikipedia.org/. n carte nu se va face referire la niciun site n limba romn.
Pagina PHP i manualul PHP se refer la paginile ociale http://php.net/ i respectiv http://
www.php.net/manual/en/. Demn de menionat este c se vor folosi doar site-urile ociale ale produselor
7

n ciuda credinelor populare, HTML nu este un limbaj de programare.


Un limbaj de programare a clientului, a browser-ului, n contrast cu PHP, cu care se programeaz serverul. n ciuda
credinelor din folclor, JavaScript i Java sunt limbaje complet diferite i de sine stttoare.
9
n cadrul programului de tutelare descris pe phpro
8

Dezvoltare web cu PHP

menionate.
Urmarea link-urilor, n special cele ctre wikipedia i ctre manualul PHP, nu este opional.
Informaiile prezentate n acele pagini fac parte din cartea de fa.

Cuvintele importante sunt scrise cursiv, termenii i noiunile importante sunt scrise nclinat, iar
cuvintele care fac referire la nume de funcii, comenzi sau instruciuni care trebuie introduse ntr-un ier
sau ca comand, sau cuvinte cheie specice unui anumit limbaj sunt scrise cu font neproporional10 .
Apsrile de taste sunt scrise n chenare, astfel ENTER nseamn apsarea o dat a tastei enter, iar
CTRL+F nseamn apsarea tastei CTRL , i n timp ce aceasta este inut apsat, apsarea adiional
a tastei F .
Codul surs, de obicei n PHP, va arta n felul urmtor:
Listing 1: Convenie listare
1
2
3

<?php
// afiseaza informatii despre PHP
phpinfo ();

Numerele de pe marginea stng reprezint numerele liniilor de cod corespunztoare i nu trebuie


scrise. Ele deservesc unei mai uoare identicri n explicaiile din text.
Simbolul trebuie interpretat ca spaiu, nu trebuie tastat ca atare. Scopul folosirii acestui simbol
este ngreunarea copierii codului surs prezentat. Este bine ca acest cod prezentat s e neles, iar
cunotinele s e aplicate scriind un cod asemntor din minte.
Atunci cnd sunt introdui termeni noi, se ofer i traducerea lor n englez, n parantez. Exemplu:
Un astfel de atac se numete man in the middle, deoarece atacatorul se a la mijloc, ntre
cele dou capete (en. endpoints).
iar la sfritul crii poi gsi o referin a tuturor acestor termeni.
Exist trei marcaje diferite pentru paragrafe:

R
U
D

Paragrafele care atenioneaz asupra unui lucru important sunt marcate ca atare, ca cel de fa.

n unele locuri se atrage atenia asupra unei practici de programare bune.


n acelai timp, cteodat se atrage atenia asupra unor lucruri care, dei sunt posibile, nu ar
trebui fcute.

Exerciiile sunt marcate cu un creion, iar numrul de stelue reprezint dicultatea lor, ntre 0 (nicio
stelu) i 3 (trei stelue). Exemplu:

Exerciiu de dicultate 1*

Eu sunt enunul unui exerciiu de dicultate 1.


Exerciiile de dicultate zero necesit doar nelegerea exemplelor i explicaiilor imediat anterioare
i mici modicri sau adugiri. Cu ct solicitarea inteligenei i a capacitii de sintez a cursantului
crete, cu att crete i numrul steluelor.
La evaluarea dicultii exerciiilor se procedez n felul urmtor: n primul rnd, se pleac de la
premiza c cursantul tie toate noiunile din capitolul anterior, chiar dac nu le-a sintetizat pe toate. n
acelai timp, se pleac de la premiza c restul capitolelor trecute au fost bine sintetizate.
10

http://en.wikipedia.org/wiki/Monospaced_font

Dezvoltare web cu PHP

Dac trebuie s sari cu mai mult de un capitol napoi pentru a revizui ceva, atunci este un
indiciu c nu ai trecut prin toate stadiile de studiu n mod consecvent. Seciunea urmtoare i
va explica care sunt aceste stadii.

Dac observi nclcri ale acestor convenii, te rog s le raportezi pe pagina de greeli a phpro.

Cum s nvei ecient programare


Momentan cartea de fa nu acoper nc materia aa cum a vrea nu este complet. ns subiectele
abordate sunt acoperite complet, cel puin la nivel conceptual.
Cartea n sine nu este gndit pentru a folosit singur, ci n paralel cu comunitatea phpro. n
particular, unele exerciii chiar nu sunt gndite pentru a rezolvate de cititor singur, ci cu susinerea
tutorilor de pe phpro.
Pe phpro gseti i ajutor sub form de idei i indicii pentru rezolvarea exerciiilor.
nva terminologia, nelege-o i folosete-o. Dac setul de scule de programare folosite este lancea ta
de programator, atunci terminologia este vrful lancei. Care este diferena dintre un toiag tocit, i o lance
fr vrf? Exact, nici una. Nu te apuca s foloesti termeni pe care nu-i nelegi, ci documenteaz-te
nainte. Cu o lance ascuit:
te vei putea nelege mai uor cu ali programatori; tu i vei nelege pe ei, i ei pe tine
pe msur ce termenii nelei de tine devin mai compleci, vei putea acumula cunotine din ce n
ce mai complexe bazate pe cele anterioare, n ritm exponential. La nceput i se va pare frustrant,
ns dac vrei s devii bun, oricum va trebui s nvei termenii odat i-odat. Deci de ce s nu
faci totul ca la carte de la bun nceput?
un programator profesionist tie mai mult de un singur limbaj de programare; ai uimit dac ai
aa ci termeni i cte concepte sunt comune multor limbaje. Dac tii terminologia, chiar dac ai
nvat-o n (cu) PHP, vei putea trece la un nou limbaj cu mult mai puine eforturi. Primul limbaj
(nvat corect) este cel mai greu, apoi i se va pare oare la ureche
Urmeaz link-urile n timp ce studiezi; acest carte nu este i nu va niciodat complet se pleac
de la premiza c citeti i nelegi ce se a la acele link-uri nainte de a trece mai departe.
Notele de subsol sunt importante; dac acestea introduc termeni neexplicai anterior sau n imediata
vecintate, atunci trebuie reinute i fcute legturi atunci cnd termenii respectivi sunt introdui pentru
prima oar.
Plec de la premiza c cititorul meu are un anumit nivel de inteligen. Asta nu nseamn c nu iau n
serios orice nelmurire. ns m atept ca noiunile prezentate s e citite cel puin, i apoi nelese. Nu
are rost s citeti o carte dac ... nu o citeti cu trup i suet. Atunci cnd ai o problem, ia-o gradual,
netrecnd la urmtorul stadiu pn nu l ndeplineti pe cel anterior.

Stadiile11 sunt: citire, nelegere, sintez, imaginaie (jonglarea cu noiunile), inovaie.

A sintetiza nseamn a face legturi cu toate celelalte noiuni deja nvate. De exemplu vei nva
ce nseamn un array, iar peste cteva capitole vei face cunotin cu obiecte. Dac vei sintetiza cum
trebuie, i vei da seama singur c este foarte posibil s ai un array de obiecte.
A jongla cu noiunile are ca efect practic faptul c cititorul tie s pun n practic i s combine
lucrurile nvate de ca i cum acele noiuni ar fost inventate de el.

11

i poi uura procesul de sintez asimilnd terminologia nc din momentul introducerii ei.

Noiunea de stadiu de nvare este extinderea autorului a sistemului japonez shu-ha-ri (en. retain-detach-transcend, jp.
). Detalii pe http://www.makigami.info/cms/japanese-learning-system-japan-36.

Dezvoltare web cu PHP


Aceast sintez e foarte important, i de fapt, o faci de cnd erai copil. De exemplu, ai vzut-o pe
mama ta tind legumele cu cuitul. Mai trziu, la joac, ai avut nevoie s tai o a, i nu aveai dect
un cuit n apropiere. i-ai dat seama c poi tia aa cu cuitul, dei nu este o legum. Altfel spus, ai
sintetizat scopul uneltei cuit: s taie ceva.
Lucrarea de fa explic foarte bine noiunile, de la zero, ns sinteza i este lsat ie. Motivaia mea
de a proceda aa este urmtoarea: dup cum sugereaz subtitlul crii Pentru nceptorii n programare
i n PHP care vor s devin profesioniti scopul meu e s te ndrum pe calea profesionalismului. Pe
de cealalt parte, sunt un darwinist convins, i dac nu reueti nici s devii profesionist, nici s vezi
utilitatea acestei cri, atunci e mai bine aa. Ultimul lucru pe care l vreau este s te susin s devii
ceva n care nu ai avea succes.
Capacitatea de sintez pe care o vei avnd la sfritul crii mai are nc un efect pozitiv asupra
viitorului profesionist din tine: n programare, vei confruntat cu nevoia de a reutiliza codul pe care-l
scrii, astfel nct s nu i nevoit s rescrii acelai cod iar i iar, doar pentru c trebuie s-l personalizezi
puin. ns pentru a putea face codul att de exibil nct s-l poi adapta cu uurin, trebuie s prevezi
cazuri imprevizibile; altfel spus, s te gndeti la imposibil.

Nu copia pur i simplu exemplele din carte, pentru c riti s te trezeti la un moment dat c
nu eti n stare s scrii ceva de unul singur. n schimb citete cu atenie codul i explicaiile
de dinaintea i dup el, apoi nchide cartea i scrie totul din minte, argumentndu-i (pe baza
explicaiilor pe care le-ai citit) de ce faci un lucru ntr-un anumit fel, sau de ce l faci de fapt.

tiu c este mai uor s copiezi, dar vor veni vremuri cnd va trebui s inventezi singur un script.
Deci obinuiete-te de pe acum s scrii singur, i de ce nu, s faci greeli. Atunci cnd faci o greeal i
PHP i spune asta, citete cu atenie mesajul de eroare, apoi corecteaz-i codul, i ine minte pentru
ecare fel de greeal ce eroare genereaz, pentru ca n viitor s poi identica mai rapid greelile pe care
le faci pe baza mesajelor de eroare pe care i le arat PHP.

Aceast putere de imaginaie, n combinaie cu capacitatea ta de analiz i sintez, i pe


o fundaie solid a nelegerii conceptelor i termenilor cu care intri n contact, sunt cheia
succesului garantat.

Comunitatea
Dezvoltare web cu PHP Pentru nceptorii n programare i n PHP care vor s devin profesioniti
nu este pur i simplu o carte, ci o comunitate i o serie de servicii pe care aceast comunitate le ofer.
Cartea de fa constituie doar scheletul, fundaia studiului. Pentru a benecia deci de aceste servicii,
cititorul crii trebuie s e i cursant n cadrul comunitii.
Pagina phpro este pagina de start a comunitii. Printre serviciile oferite se numr:
vericarea soluiilor exerciiilor i oferirea de indicii acolo unde cursantul s-a blocat, individual,
pentru ecare cursant n parte, exact acolo unde are nevoie
claricarea nelmuririlor pe care cursantul le are n urma citirii explicaiilor
articole care ntregesc conceptele prezentate n carte; excursuri
garania c cursanii12 au ntr-adevr potenialul de a deveni profesioniti
servicii care sunt folosite n viaa real a unui programator
Comunitatea phpro nu este un loc unde poi primi ajutor la problemele de care te-ai lovit pe cont
propriu. Altfel spus, comunitatea noastr este strict una de studiu.
12

n special cei care au reuit s ofere soluii la primele trei exerciii din capitolul 2, eventual cu susinerea tutorilor

10

Dezvoltare web cu PHP

Exerciiile
Exerciiile sunt parte integrant a studiului. Scopul exerciiilor nu este numai de a te testa, ci i de
a te nva lucruri noi. De fapt, unele exerciii au menirea exclusiv de a te nva ceva.
Indiferent de menirea ecrui exerciiu, poi apela la comunitatea phpro pentru susinere, sfaturi i
indicii la exerciii. n fapt, chiar va trebui s o faci la unele exerciii vei avea nevoie de asta.
Desprinzndu-te de comunitatea phpro, riti s studiezi ceva de unul singur i s ai impresia c ai
neles totul corect, ns lucrurile nvate se pot aterne greit n mintea ta, i la un moment dat te vei
lovi tu nsui de probleme din cauza asta.
Avnd ns permanent, la ecare exerciiu, un tutore lng tine care te ndrum, ansele ca un concept
de programare s e neles i aplicat greit scad considerabil.
Unele exerciii vor direct legate de comunitate i de serviciile pe care aceasta le ofer. n capitolul
patru de exemplu, exerciiile i vor cere s formezi echipe cu ali cursani, i s concurezi mpotriva altor
echipe, folosind scule de programare aa cum sunt folosite n viaa real a unui programator, precum un
bug tracker sau un revision control system.
ns pentru a primi acces la aceste servicii pe care comunitatea phpro le ofer gratis, trebuie s rezolvi
toate exerciiile anterioare sub tutela comunitii, dovedind astfel c ai potenialul unui programator bun.

Cum pot ajuta?


Att programatorii experimentai, ct i nceptorii, pot ajuta, iar ajutorul lor este apreciat n egal
msur.
Punctul de ntlnire pentru toi este phpro, unde poi gsi ndrumare despre ce poi face, sau unde
poi raporta ce ai de raportat.
De la cititorii avansai m atept la critic constructiv, sfaturi sau idei. Feedback-ul m bucur,
ns vreau s atrag atenia asupra unui lucru: exist situaii n care, atunci cnd trebuie s explici ceva,
trebuie s faci compromisuri ntre corectitudinea tehnic i uurina cu care noiunile pot acumulate de
cititor (en. the learning curve), iar cu compromisurile suntem obinuii din programare. Aa se face c
pe alocuri ofer explicaii nu tocmai corecte, care sunt corectate apoi. Asigur-te c ai citit tot coninutul
relevant (i mai ales notele de subsol) nainte de a raporta o greeal cel mai probabil explicaiile sau
deniiile sunt reluate i lefuite undeva.
n privina calitii crii, exist trei mari probleme:
Nu cred n cacofonii. Consider c propria imaginaie e singura vinovat dac vezi alte lucruri
cnd citeti. Ca atare, refuz s le corectez. Ba mai ru, corectarea lor prin folosirea virgulei sau
reformulri mai mult ar ngreuna inteligibilitatea.
Folosesc xenisme. Resursele n limba englez sunt cele mai acurate i cele mai actuale, din acest
motiv nu ncerc s evit folosirea lor. Asta i va permite, pe termen lung, s te poi ajuta singur.
Pentru a articula un xenism pun cratim, i apoi particula specic. De exemplu web-ul; ns:
Internetul deoarece cuvntul internet exist n limba romn.
Este foarte posibil s ntlneti formulri ciudate, cu ordinea cuvintelor inversat, i altfel de greeli
similare. Cauza acestui lucru este c 90% din timp vorbesc germana, lucru care-i las amprenta.
Corecturile sunt binevenite.

O privire de ansamblu a capitolelor


1. Reelistic noiunile de reelistic sunt necesare pentru a nelege mai uor apoi lucruri legate de
securitate, optimizare sau servicii web

11

Dezvoltare web cu PHP


2. Controlul uxului de execuie i de date te nva constructele pentru controlul informaiilor n
cadrul aplicaiei
3. Reutilizarea i modularizarea codului mprirea codului n funcii i iere, separarea logicii
aplicaiei de vizualizare
4. Baze de date i lucrul n echip cum s lucrezi n echip, de la anumite reguli de comunicare,
pn la mailing lists i git; documentarea proiectului; debugging i proling pentru a lua cele mai
bune decizii; database design pn la i inclusiv 3rd normal form
5. Securitatea aplicaiilor web XSS, sql injection, CSRF
6. Programare orientat pe obiecte OOP, concepte generale, cteva patterns (helper, strategy,
factory, singleton), test-driven development, SPL
7. ajax, json, servicii (REST, SOAP, XML-RPC), XML, PDO i alte delicii, i ca ultima frontiera:
php internals.
ncepnd cu capitolul 4 proiectele se vor realiza n echipe, iar tutorii vor avea doar rolul de
consilieri. Proiectele rezultate astfel vor aparine respectivilor programatori, i vor putea folosite
pentru portofoliile cursanilor.

12

Capitolul

Reelistic
Cu PHP controlezi ce se ntmpl pe server,1 server care este conectat la Internet. Deci folosirea
PHP este strns legat de reea. Din acest motiv, nelegerea noiunilor fundamentale de reelistic este
indispensabil.2 Nu voi intra n toate detaliile, doar n ce ai nevoie ca programator i pentru a-i seta
mediul de programare n PHP, pentru a crea website-uri sigure, i pentru a nelege noiunile necesare n
folosirea extensiilor PHP care lucreaz cu reeaua.

Noduri, TCP/IP, reele


Reelistica (en. networking) se ocup cu comunicarea ntre aa-zise noduri (en. nodes). Un nod poate
un calculator personal, un router, un server, practic orice dispozitiv digital conectat la reea.
nainte de a vedea printr-un exemplu practic prin ce noduri din reea trec informaiile atunci cnd
caui ceva pe web cu google, trebuie s faci cunotin cu cteva deniii generale.
Exist dou mari tipuri de interfee pentru interaciunea cu un sistem de operare (en. operating
system)3 :
GUI (en. graphical user interface)
Este cea mai comun printre utilizatorii ocazionali, este uor de utilizat i nu necesit cunotine
avansate de IT pentru a o folosi. ns te limiteaz n folosirea programelor
CLI (en. command line interface)
Este destinat profesionitilor. Necesit cunotine mai avansate, ns este mult mai puternic i
exibil
Sub MS Windows, interfaa CLI este cunoscut i ca MS-DOS Prompt. Pentru a-l lansa n execuie,
du-te n Start -> Run, i tasteaz cmd. Apare o fereastr neagr i neprietenoas. Sub GNU/Linux
aceasta este cunoscut sub numele de consol, terminal sau shell (unul dintre ele ind bash).
Deschide interfaa CLI a sistemului tu i introdu comanda tracert google.com pentru Windows
sau traceroute google.com pentru GNU/Linux. Figura 1.1 i d un exemplu de output.
Dup cum vezi, tot ceea ce i trimit eu lui google.com i ce mi trimite el napoi trece prin alte 11
noduri din reea. Dac un infractor (en. cracker) deine controlul asupra unuia dintre aceste noduri,
1

n acest capitol vei vedea c termenul server este deseori folosit greit, ca i n acest paragraf.
De exemplu pentru nelegerea implicaiilor de securitate, folosirea extensiilor precum cURL sau cereri asincrone
AJAX. Nu i face griji dac nu nelegi toi aceti termeni deocamdat.
3
abv. OS
2

13

Dezvoltare web cu PHP

1.1. NODURI, TCP/IP, REELE

Figura 1.1: Ruta ctre un nod


poate vedea absolut orice vorbesc eu cu google.com. Un astfel de atac se numete man in the middle,
deoarece atacatorul se a la mijloc, ntre cele dou capete (en. endpoints).
Bineneles c nu numai eu a victima unui astfel de atacator, ci oricine trimite pachete de date (en.
data packets) oricui altcuiva (nu neaprat numai lui google.com), atta timp ct pachetele de date trec
prin nodul controlat de el.
Toate nodurile din reeaua global numit Internet au o adres unic numit adres IP (en. internet
protocol). Ea este de forma xxx.xxx.xxx.xxx, unde xxx este un numr ntre 0 i 255. Unele adrese
IP au o semnicaie special. De exemplu, ecare nod are adresa IP 127.0.0.1. Ea nu este util n
Internet, deoarece orice pachet de date trimis la acea adres ajunge napoi la expeditor, fr nici mcar
a trece pragul sistemului local. ncearc de exemplu comanda tracert 127.0.0.1.
Alt bloc de adrese IP speciale sunt toate adresele ntre 192.168.0.0 i 192.168.255.255. Ele sunt
rezervate reelelor locale (en. local area network).4
Un astfel de exemplu este chiar reeaua mea local5 . Dup cum vezi n gura 1.1, pachetele de date
care pleac de la mine trec mai nti prin nodul 192.168.2.1. Aceasta este adresa router-ului6 meu.
Topologia reelei din perspectiva mea arat ca n gura 1.2.

Figura 1.2: Exemplu de topologie a unui LAN


Misiunea unui router este s distribuie pachetele pe care le primete altor calculatoare din LAN-ul
meu. Asta mi permite s am acces la Internet cu mai multe calculatoare, ns din exterior LAN-ul este
vzut ca avnd o singur adres IP: 84.43.53.126, i deci ca un singur calculator. Dac nu puneam acest
router ntre calculatoarele mele i Internet, nu puteam conecta la Internet dect un singur calculator,
care avea adresa IP 84.43.53.126.
Exist deci dou tipuri de adrese IP, cele interne reelei mele, precum 192.168.2.1 sau 192.168.2.6
4

abv. LAN
Un bun punct de start este http://en.wikipedia.org/wiki/Private_network. De acolo poi urma link-uri intersante
ctre noiunile ce urmeaz a introduse, i multe alte lucruri neprezentate aici.
6
http://en.wikipedia.org/wiki/Router
5

14

Dezvoltare web cu PHP

1.2. DOMENII

i cele externe reelei, publice, precum 84.43.53.126 sau una dintre adresele lui google.com,
74.125.87.104. Cele dinti se numesc adrese private7 sau adrese LAN, cele din urm sunt n schimb
adrese publice.

Internetul este o reea de LAN-uri i WAN-uri (en. wide area network) interconectate. Asta
transform Internetul n cea mai mare WAN, o reea global.

Dac nu ai un router la mijloc, ntre tine i Internet, atunci i poi vedea adresa IP extern prin
interfaa pus la dispoziie de sistemul tu de operare. Sub windows, introdu comanda ipconfig /all
n CLI, sub GNU/Linux ifconfig -a.
Dac ns ai un router la mijloc, i nu tii cum s-i accesezi interfaa de congurare, atunci trebuie
s i ceri unui alt calculator de pe Internet s-i spun ce adres IP vede el c ai, pentru c ce vede el va
mereu adresa ta Internet, extern.

What is my IP Address?*

Caut pe web cu un motor de cutare what is my ip address i compar adresa aat de acea aplicaie
web cu ce adres IP i raporteaz OS-ul tu. Ce poi deduce din aceast comparaie, legat de topologia
reelei tale?

Domenii
Teoretic, este sucient s tii adresa IP a unui nod pentru a comunica cu el. De exemplu, am aat
c una dintre adresele IP ale lui google.com este 74.125.87.104. Deci putem intra bine mersi pe adresa
http://74.125.87.104.
ns oamenii nu pot reine uor numere. De aceea s-a inventat DNS (en. domain name system),
un sistem care convertete nume precum google.com, n adrese IP. Atunci cnd introduci google.com
n browserul tu, acesta trimite o cerere la serverul DNS i primete napoi adresele IP asociate cu
google.com. Abia apoi se conecteaz la acea adres IP, i i cere informaii.
Sub MS Windows i poi aa serverele DNS cu aceeai comand ipconfig i parametrul /all. Sub
GNU/Linux, acestea se a n mod normal n ierul /etc/resolv.conf.
S presupunem c serverele tale DNS se deconecteaz de la reea.8 Atunci nu vei mai putea accesa
http://google.com, pentru c browserul tu nu mai poate aa adresa IP corespunztoare. ns asta nu
te mpiedic s introduci manual adresa IP, dac o tii.
Pentru a aa dac un nod este conectat la reea se folosete comanda ping9 , avnd primul parametru
adresa IP pe care vrei s o verici.

Ping your DNS server

A adresa IP a serverului tu DNS i trimite-i un pachet de date cu ping.10


Poi interoga manual serverul DNS cu comanda nslookup (en. nameserver lookup). Exemple:
nslookup google.com, nslookup 192.0.32.10. Este deci posibil s ai att adresele IP pornind de la
un nume precum google.com, ns i numele, pornind de la o adres IP de Internet (nu de intranet).
7

le poi numi i intranet, analog cu cele publice, internet.


O glum comun este s spui c administratorul serverului s-a mpiedicat din greeal de stecher i l-a tras din priz
fr s i dea seama.
9
o numim comand, ns n realitate este un program, i se numete ping.exe
10
Acest exerciiu nu trebuie rezolvat n cadrul programului de tutelare, este un exerciiu suplimentar, pentru tine.
8

15

Dezvoltare web cu PHP

1.3. PROTOCOALE

Dei este posibil ca mai multe domenii s pointeze ctre aceeai adres IP, o adres IP nu poate pointa
(prin reverse DNS) dect spre un domeniu.11
Totui, din ce este compus o adres precum www.google.com? .com se numete TLD (en. top level
domain). Ceea ce se a n stnga sa este un subdomeniu, pn la urmtorul punct. Astfel, google este
un subdomeniu al lui .com, iar www este un subdomeniu al lui .google.com.
Dac vrei s ai un domeniu al tu, trebuie s cumperi unul de la o rm numit domain name
registrar. Pentru a nva PHP nu ai nevoie de un domeniu, poi face totul pe calculatorul tu personal,
aa cum vei vedea n acest capitol.

Protocoale
Internetul este fcut din aa-numite servicii. Cele mai cunoscute servicii sunt web-ul pentru
documente interconectate,12 pop3 sau imap pentru e-mail, irc (en. internet relay chat) pentru chat,
sau ftp (en. le transfer protocol) pentru transferul de iere.
Pentru a folosi unul dintre aceste servicii, ai nevoie de un program special numit client. Nu exist un
client care s tie s acceseze toate serviciile, pentru c ecare serviciu este diferit de celelalte. Vom
vedea mai trziu de ce.
Astfel, avem clieni pentru www, clieni pentru ftp, clieni pentru irc, .a.m.d.
Serviciul world wide web, sau pe scurt web-ul, este att de rspndit, nct oamenii au dat un nume
special clienilor www: browser. Exist mai multe browsere, create de diferite rme. Printre cele mai
cunoscute se numr:
Firefox, creat de Mozilla
Internet Explorer, creat de Microsoft
Opera, creat de Opera Software
Google Chrome, creat de Google
Safari, creat de Apple
Colocvial vorbind, te poi referi la client i ca ind calculatorul pe care ruleaz clientul, sau chiar
la utilizatorul uman din spate care i d instrucii clientului. n explicaii voi ncerca s nu m exprim
colocvial, ci corect din punct de vedere tehnic.
n continuare vom clarica ce se ntmpl atunci cnd ceri o pagin web cu ajutorul unui browser de
la un server.
Imagineaz-i c un calculator st conectat la reea i nu face nimic din proprie iniiativ. Acest
calculator se numete server. Pe server, care este maina zic, ruleaz un program numit daemon.
Acesta ateapt conexiuni din exterior, pe care s le deserveasc. Administratorul serverului va spune
colocvial the server is up and running, dar ce vrea s spun de fapt este c serverul este conectat la
Internet iar cel puin un daemon ateapt noi conexiuni.
S nu uitm c ecare serviciu este diferit. Aa cum avem diferii clieni pentru diferite servicii, tot
la fel avem i daemon-uri diferite pentru ecare serviciu.
Exemple de astfel de daemon-uri: apache pentru serviciul www, UnrealIRCd pentru irc, postx pentru
e-mail, .a.m.d. Reine c acestea sunt programe, la fel cum este i firefox.exe. n contrast cu asta
noiunile de client i daemon sunt clasicri generice pentru tipuri de software.
Ceea ce nu am ncetat s sugerez pn acum devine evident: cele dou pri, clientul serviciului
pe care doresc s-l utilizez, i daemonul care e capabil s-i rspund clientului meu cu informaii utile,
trebuie s comunice unul cu cellalt.
11
12

Tehnic este posibil, ns practic poate cauza probleme.


Prin link-uri.

16

Dezvoltare web cu PHP

1.3. PROTOCOALE

Aceast comunicare dintre cele dou programe se va desfura ntr-un limbaj comun numit protocol.
Fiecare serviciu are un protocol specic lui. Astfel avem un protocol irc pentru serviciul irc, protocolul
ftp pentru serviciul ftp, sau protocolul http pentru serviciul web, .a.m.d. De aici vine acel http://
care precede orice adres web. Aceast adres se numete URL (en. uniform resource locator), o form
de URI (en. uniform resource identier).
De obicei pe un server ruleaz mai multe daemon-uri n paralel i care ateapt s deserveasc cereri.
Dar cum s tie sistemul de operare al serverului pentru ce daemon este destinat un anumit pachet de
date? Din cte tim pn acum, nu are cum, pentru c OS-ul nu nelege noiunea de protocol. Totui
OS-ul trebuie s paseze datele primite pachet cu pachet daemon-ului corect.
Pentru a rezolva aceast problem ecare pachet de date este nsemnat cu un port. Un port este
un numr ntre 1 i 65535 care i permite sistemului de operare s paseze pachetul de date procesului13
corect.
Atunci cnd administratorul serverului (en. sysadmin) lanseaz n execuie un daemon, acesta i
spune OS-ului c ascult (en. listen) pe un anumit port. Din acel moment, OS-ul tie c acel port i
aparine acelui daemon. Astfel, sysadmin-ul poate rula pe sistemul su mai muli daemoni concomitent,
chiar i pentru servicii diferite, fr a-i face griji c pachetele de date ar putea ajunge la daemon-urile
greite.
Important de menionat este i c ecare serviciu are un port standard. Serviciul www are 80 ca port
standard. Astfel, URL-urile http://example.com:80 i http://example.com sunt absolut echivalente.
n toate cele explicate pn acum nu am intrat n detalii importante precum TCP/IP, ns este
recomandat citirea i nelegerea acelor noiuni, ct i a celorlalte articole pe care le poi urma de acolo.
Foarte important este i nelegerea modelului OSI (en. open system interconnection).

1.3.1 Primul exerciiu de hacking


nainte de a trece la coninutul propriu-zis, vreau s claric de ce aceast seciune folosete termenul
hacking.
n primul rnd, pentru a face acest capitol mai atractiv pentru toi cititorii care s-au plictisit de teoria
uscat14 de reelistic prezentat pn acum, cnd ei vor de fapt s nvee PHP. Nu este ceva iluzoriu,
ceea ce vei face n continuare chiar are de-a face cu hacking. ns hacking implic mult mai multe15
cunotine paginile anterioare doar i-au prezentat sumar nite concepte de baz.
n al doilea rnd, pentru a-mi crea ocazia de a explica termenul de hacker. n zilele noastre, massmedia, n ncercarea sa de a crea16 senzaionalul, a redenit hacker ca infractor. ns nu asta este
semnicaia original a cuvntului. Un hacker este o persoan care nelege foarte bine ce face. Poi
un hacker n orice domeniu, dar atunci cnd devii un hacker ntr-un domeniu, tii tot ce mic n brana
ta. Un hacker n calculatoare tie totul despre calculatoare, ncepnd de la electronica procesorului, i
terminnd cu analiza psihologic a omului n relaia sa cu calculatorul (sau, pe larg, cu tehnologia n
general).17
O alt concepie greit despre hacking este c nseamn s intri n sisteme care nu-i aparin (s le
spargi). Nu asta caracterizeaz hackerul, ci dup cum am mai spus, nelegerea lucrurilor cu care are de-a
face. Te poi numi hacker la fel de bine dac personalizezi un program scris de altcineva pentru nevoile
tale. n astfel de cazuri se spune c ai hack-uit codul surs, c l-ai neles mai nti, pentru a-l putea
modica. Dup cum vezi, hacking nseamn nelegere.
Felul n care aplici aceast nelegere depinde de tine. Asta nu i absolv pe cei care folosesc ceea
ce tiu pentru lucruri ilegale s e catalogai drept infractori. Pe de cealalt parte, hackerii adevrai
reacioneaz acid cnd sunt privii ca nite infractori, deoarece ei tiu c hacking este de fapt ceva
13

Un program care este executat. Gndete-te la ce listeaz task manager.


Trebuie s recunoatem c nu a fost deloc uscat.
15
i cnd spun asta, nu exagerez.
16
n sensul de a inventa
17
Cel mai renumit exemplu este Kevin Mitnick
14

17

Dezvoltare web cu PHP

1.3. PROTOCOALE

constructiv i benec unei mini sntoase. Ei prefer ca infractorii s e numii crackeri, pentru a
deosebi binele de ru.
...................................................................................................
Atunci cnd introduci un URL ntr-un browser, acesta face multe lucruri n fundal. Unul dintre
cele mai importante lucruri este comunicarea n limbajul HTTP (en. hyper text transfer protocol) cu
daemon-ul de pe serverul dorit, asta dup ce a aat adresa IP a acestuia de la serverul DNS.
Noi vrem s facem manual ceea ce ar face un browser automat pentru noi. Pentru asta, avem nevoie
de un program numit telnet. Este un program foarte simplu, tot ce face este s stabileasc o conexiune
cu daemonul, i s-i transmit datele pe care le tastm.
O dat ce conexiunea este stabilit, ambele endpoints (daemonul i noi, cu ajutorul clientului telnet)
pot scrie la grmad date. De exemplu dac noi scriem
foo
i daemonul ne rspunde cu
bar
atunci toate datele comunicate arat ca un ier cu coninutul:
foo
bar
Imagineaz-i c dou endpoints comunic prin plicuri. Programul care iniiaz conexiunea (numit
client), scrie datele pe care urmeaz s le trimit ntr-un plic.
Dac clientul i daemonul doar schimb date aa cum sunt, aa cum am face cu telnet, atunci doar
acest plic este necesar. ns dac aplicaiile vor s se neleag reciproc, ele trebuie s foloseasc un
protocol de comunicare. Pentru web, acest protocol este HTTP.
Acest protocol de comunicare constituie layer-ul application level din modelul OSI.18
n astfel de cazuri, clientul va trebui s pun n plicul nostru nc un plic19 cu datele structurate
specice protocolului folosit, n cazul nostru cele specice protocolului HTTP.
Majoritatea sistemelor de operare moderne vin cu programul telnet preinstalat. Deci deschide
interfaa CLI i lanseaz programul, pasndu-i ca prim parametru numele serverului, i port-ul ca al
doilea parametru, deci:
telnet example.org 80
Dup ce s-a conectat, i poi cere daemonului ce document vrei, ns trebuie s o faci n limbajul HTTP,
altfel nu va nelege ce vrem de la el. Altfel spus, folosind analogia cu plicul, noi ca oameni, deoarece
tim c vrem s comunicm n HTTP, i deoarece telnet nu are noiunea de application layer, avem
responsabilitatea de a ne mpacheta singuri cererea n nc un plic cu formatul specic HTTP, plic pe
care i-l pasm lui telnet, care ne va pune plicul pe rnd n toate celelalte layere (plicuri) din modelul
OSI aate sub application layer: presentation, session, transport, network, iar electronica (de exemplu
placa de reea) se va ocupa de data link layer i physical layer.20
De exemplu, i vom cere pagina de start:
GET / HTTP/1.1 Host: example.org 18

http://en.wikipedia.org/wiki/OSI_model
sau mai multe, n funcie de protocolul de comunicare folosit
20
Lucrurile sunt mult mai complexe, telnet singur nu ar putea face astfel de lucruri fr susinere din partea sistemului
de operare. Aici am simplicat imaginea pentru o mai uoar nelegere.
19

18

Dezvoltare web cu PHP

1.3. PROTOCOALE

Simbolul - nseamn c trebuie s apei tasta enter . Deci pentru a termina cererea HTTP,
apei de dou ori enter la rnd. Este posibil ca programul tu telnet s nu aeze ce tastezi.
n acest caz, trebuie s scrii orbete, i s o faci exact ca mai sus, inclusiv scrisul cu litere
mari/mici.

GET este metoda HTTP (en. http method) pe care o folosim pentru a cere resursa (documentul)
dorit.
Protocolul21 HTTP ne dicteaz c dup GET urmeaz un spaiu i apoi calea ctre documentul dorit,
urmat de protocolul folosit, aici HTTP, un slash, i versiunea protocolului.
Prima linie GET / HTTP/1.1 se numete request line. Dup ea urmeaz o serie de request headers,
precum Host mai sus.
Request line i request headers mpreun sunt cunoscute i ca cererea HTTP (en. HTTP request).
Daemonul i va rspunde cu un text care arat cam aa, i care constituie rspunsul HTTP (en.
HTTP response):
HTTP/1.1 200 OK
Server: Apache/2.2.3 (Red Hat)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
ETag: ``b300b4-1b6-4059a80bfd280''
(1) Accept-Ranges: bytes
Content-Type: text/html; charset=UTF-8
Connection: Keep-Alive
Date: Tue, 15 Dec 2009 11:52:46 GMT
Age: 2528
Content-Length: 438
<HTML>
<HEAD>
<TITLE>Example Web Page</TITLE>
</HEAD>
<body>
(2) <p>You have reached this web page by typing &quot;example.com&quot;,
&quot;example.net&quot;,
or &quot;example.org&quot; into your web browser.</p>
<p>These domain names are reserved for use in documentation and
are not available for registration.
See <a href=``http://www.rfc-editor.org/rfc/rfc2606.txt''>
RFC 2606</a>, Section 3.</p>
</BODY>
</HTML>
ntreaga comunicaie cu daemonul este deci compus din trei segmente mari, ecare separate printr-o
linie goal, rezultat din apsarea de dou ori a tastei enter : HTTP request, HTTP response headers
(segmentul (1) din outputul de mai sus), i HTTP response body (segmentul (2)).
Felul n care se face cererea este parte din specicaia limbajului de comunicare HTTP. Acest limbaj,
ca i multe altele, au fost stabilite prin aa-numitele RFC-uri (en. request for comments).
Folosind analogia cu plicurile, cele apte niveluri din modelul OSI nu sunt totul: protocolul HTTP
nsui mai denete nc trei plicuri care trebuie puse n plicul cu datele HTTP:
HTTP request
response headers
21

Formatul

19

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

response body
Chiar dac cele trei segmente sunt scrise e de client, e de daemon, noi privim ntreaga comunicaie ca
pe un ier unitar, i din acest motiv putem spune c este constituit din aceste trei segmente (plicuri).
Dup ce a primit rspunsul HTML, un browser ar face alte lucruri precum:
crearea de cereri noi pentru ecare element care face referire la resurse externe precum imagini,
frame-uri, scripturi Javascript, .a.m.d. n urma acestui pas imaginile ar prea c fac parte din
document, ns ele sunt de fapt resurse diferite i de sine stttoare, cu URL-uri diferite.
executarea scripturilor Javascript
Deoarece pentru ecare resurs extern este necesar crearea unei noi conexiuni TCP/IP i
comunicarea cu serverul n limbajul HTTP, protocolul HTTP este un protocol stateless22 .

HTTP e stateless

Faptul c HTTP este un protocol stateless are implicri majore asupra structurii fundamentale n
care i vei concepe aplicaiile.
Gndete-te la aceste implicri i explic-le n 200-300 cuvinte.
ns clientul nostru telnet nu tie toate aceste lucruri, el nu nelege limbajul de comunicare HTTP pe
care l-am folosit,23 cum nu nelege nici limbajul de formatare HTML, n consecin nici nu poate aa
imagini sau executa scripturi Javascript. El doar s-a conectat la daemon pe portul dorit de noi, i ne-a
oferit posibilitatea de a comunica cu el n HTTP pentru a primi codul HTML al paginii.
Dac n acest moment am vrea s cerem daemonului un alt ier, i nu cel standard, ar trebui s nu-i
cerem resursa / (care urmeaz dup GET n cererea anterioar, i care este numit i root), ci numele
resursei cu tot cu calea sa absolut. De exemplu, pentru ierul http://example.org/contact.html,
cererea ar arta astfel:
GET /contact.html HTTP/1.1
Host: example.org
Motivul pentru care trebuie s specicm la ce domeniu ne referim n cmpul (en. header eld)
Host (aici: example.org) este c un daemon HTTP poate deservi mai multe domenii simultan, i
deci trebuie s-i spunem la care din ele ne referim. De exemplu, este posibil ca http://example.org
i http://www.example.org s e dou site-uri complet diferite, independente, cu iere diferite.
ntmpltor, administratorul care a setat acel apache 2.2.3 (tim c acel program cu acea versiune
deservete acel site din response header-ul Server) a fcut setrile astfel nct cele dou hostnameuri complet diferite example.org i www.example.org s fac referire ctre acelai director de pe server.
Din acest motiv nu conteaz ctre ce hostname trimitem cererea, daemonul ne va rspunde cu aceleai
iere.

Instalarea mediului de dezvoltare


n aceast seciune vom instala cele dou scule necesare crerii i testrii aplicaiilor web, sau mai bine
spus, scripturilor PHP. M voi limita doar la instruciuni pentru Microsoft Windows XP24 . Instalarea
sub GNU/Linux este uoar: nu trebuie dect s instalezi pachetele de genul apache sau httpd i PHP
22

http://en.wikipedia.org/wiki/Stateless_protocol
Protocolul de comunicare este plicul ce corespunde application layer n modelul OSI.
24
Instalarea sub Windows Vista sau Windows 7 este asemntoare.

23

20

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

din repozitoriul pus la dispoziie de distribuia ta, aa cum ai instala orice alt program. Directivele de
congurare sunt foarte similare, deci o citire a instruciunilor urmtoare nu este de prisos, chiar dac
foloseti GNU/Linux.
Paii i instruciunile de congurare sunt aceeai, att pentru windows, ct i pentru GNU/Linux.
n primul rnd, intr pe pagina ocial a daemonului apache25 i urmeaz linkul Download a ultimei
versiuni, momentan26 2.2.1927 .

Figura 1.3: Pagina ocial Apache HTTPD


Alege un mirror 28 i apas change. Mirror-ul selectat automat ar trebui s e unul dintre cele mai
bune. Apoi selecteaz versiunea Win32 Binary without crypto.
Introdu datele ca n gura 1.4 i treci la pasul urmtor.

Figura 1.4: Setarea iniial apache httpd


Alege modul de instalare custom, deoarece vrem s decidem exact unde i ce se instaleaz, ca n 1.5.
25

http://httpd.apache.org/
08.08.2011
27
Tot timpul este bine s alegi ultima versiune, cea stabil.
28
Un mirror este o oglindire a unor iere. Mai multe rme sau instituii au ales s pun la dispoziie oglindiri ale ierelor
de instalare pentru apache. Oricine poate face un mirror, ns e recomandat s ntiinezi autorul ocial, pentru ca acesta
s pun un link ctre mirror-ul tu. Toate ierele de pe un mirror sunt identice, deci teoretic nu conteaz ce mirror alegi,
ns este recomandat s alegi un mirror apropiat ie din punct de vedere geograc, pentru ca descrcarea s e mai rapid.
26

21

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

Figura 1.5: Setare personalizat


n gura 1.6 avem un arbore cu toate componentele instalate. Apache HTTP Server 2.2.14 este
printele tuturor componentelor. Selecteaz-l i apas pe butonul Change... pentru a schimba locul de
instalare.

Figura 1.6: Setare httpd - Componentele instalate


Creaz un nou director C:\webdev\ unde vor instalate toate sculele de programare web, introducnd
manual calea C:\webdev\apache exact ca n 1.7.
Conrmarea te va aduce la dialogul anterior, iar n partea de jos ar trebui s scrie c programul va
instalat la acea locaie.
Finalizeaz instalarea. La vizitarea adresei http://localhost/ ar trebui s vezi mesajul It works!.
Asta nseamn c daemonul apache este setat corect i poate deservi pagini statice n formatul html, iar
calculatorul tu este acum un server.
Noi ns vrem s generm n mod dinamic cod HTML cu PHP. Deci intr pe pagina ocial PHP29 i
urmeaz linkul de download, sub Windows binaries30 . Selecteaz tipul de executabil VC9 x86 Thread
Safe pentru versiunea PHP 5.3, ca n 1.8, apoi descarc arhiva .zip care conine PHP, salvnd-o n
C:\webdev\.
29

http://php.net
n prile ce urmeaz se folosete versiunea 5.3.6, dar tu trebuie s alegi ultima versiune stabil. Important este doar s
selectezi versiunea compilat cu VC9, care este thread-safe.
30

22

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

Figura 1.7: Setare httpd - Calea instalrii

Figura 1.8: PHP - Tipul build-ului PHP


Dup dezarhivare, coninutul su va arta ca n Figura 1.9.

Figura 1.9: PHP - What you get


nainte de a trece la integrarea lui PHP n apache, i recomand s instalezi un editor text ideal pentru
nceptorii n programare: Notepad++ 31 , de pe pagina ocial.

Notepad++ este foarte bun ca editor deoarece, ind un editor text, vezi exact ce faci, prelund
controlul, aa cum ar trebui s o fac orice programator. Pe lng asta, Notepad++ i i
coloreaz textul dac recunoate limbajul n care scrii acel text, precum PHP sau HTML.

Dac eti cumva tentat s foloseti editoare WYSIWYG32 precum Dreamweaver, atunci ar
trebui s te opreti acum - programarea nu e pentru tine. De ce? n afar de faptul c un
astfel de editor nu te-ar stimula s nvei, i-ar i crea mai multe probleme. Cu PHP, tu ca
programator vei prelua controlul i vei genera HTML. Pe lnga asta, astfel de programe nu sunt
destul de puternice ca o minte uman, i mai i genereaz cod greit.

31

http://notepad-plus.sourceforge.net/

23

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

PHP poate folosit i ca limbaj de scripting general, nu doar pentru generarea dinamic de HTML.
ns pentru asta trebuie setat calea ctre directorul php care conine ierul de congurare php.ini,
asupra cruia voi reveni puin mai trziu.
Sub Windows XP, click dreapta pe My Computer i apoi Properties. Sub Windows 7, n start ->
run introdu comanda:
C:\Windows\System32\SystemPropertiesAdvanced.exe
Alege tabul Advanced, apoi click pe Environment Variables n partea de jos a dialogului, aa cum
vezi n Figura 1.10.

Figura 1.10: Proprietile avansate ale sistemului Windows XP


Se va deschide un dialog similar cu cel din Figura 1.11.

Figura 1.11: Variabilele de mediu ale unui sistem Windows


Click pe New sub System variables, i introdu datele ca n Figura 1.12. Aceast nou variabil de
mediu l va ajuta pe PHP s-i gseasc ierul de congurare php.ini.
32

what you see is what you get

24

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

Figura 1.12: Variabilele de mediu ale unui sistem Windows


n acest moment, PHP este setat i l-am putea lansa n execuie folosind calea absolut
C:\webdev\php-5.3.6\php.exe, ceea ce poate deveni obositor cu timpul. ns putem integra php.exe
n sistem astfel nct s e recunoscut ca comand.
Pentru ca asta s se ntmple, identic variabila systemului numit Path i adaug-i la sfrit:
;C:\webdev\php-5.3.6\, ca n Figura 1.13.

Figura 1.13: Variabila de mediu PATH

Acel ; de la nceput este foarte important. PATH conine o list de directoare n care windows
se va uita pe rnd atunci cnd lansezi n execuie un program ca pe o comand. ; are rolul de
a separa aceste directoare.

Un singur lucru mai lipsete: php.ini. Arhiva pe care tocmai ai descrcat-o vine cu dou astfel de
iere, php.ini-development i php.ini-production. F o copie a ierului php.ini-development i
redenumete-o php.ini.
Testeaz dac ai setat totul cum trebuie deschiznd o nou instan a promptului ms-dos. Acolo
introdu comanda php --ini. Totul este corect dac php este gsit de sistem, iar comanda de mai sus i
arat C:\webdev\php-5.3.6\php.ini ca Loaded Conguration File.
Acum vom trece la integrarea lui PHP ca modul apache. Vom spune c folosim SAPI-ul33 (en. server
application programming interface) apache2. n directorul n care ai instalat apache este un subdirector
de congurare numit sugestiv conf/, unde rezid toate ierele de congurare pentru apache.
Fiierul principal de congurare al apache se numete httpd.conf. Este singurul ier ncrcat
automat de apache pentru a citi conguraia, celelalte iere trebuie incluse folosind directiva Include
din acest ier principal (en. the master conguration le). Liniile care ncep cu caracterul diez (#)
sunt comentarii, iar coninutul lor nu este luat n considerare, chiar dac conine directive de congurare
valide.
Deschide httpd.conf cu notepad++ i adaug-i la sfrit (combinaia CTRL+END ) directiva Include
conf/extra/httpd-php.conf apoi creaz un nou ier cu CTRL+N cu acest coninut:
LoadModule php5_module "C:/webdev/php-5.3.6/php5apache2_2.dll"
AddType application/x-httpd-php .php
PHPIniDir "C:/webdev/php-5.3.6"
<IfModule dir_module>
DirectoryIndex index.php index.html
33

http://en.wikipedia.org/wiki/Server_Application_Programming_Interface

25

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

</IfModule>
Acum
apas
CTRL+S
i
salveaz-l
ca
httpd-php.conf
n
directorul
C:\webdev\apache\conf\extra\
Directiva LoadModule i spune s ncarce un ier ca modul apache. AddType l instruiete s
interpreteze iere ce se termin n .php ca application/x-httpd-php, care este un tip MIME34 (en.
multipurpose internet mail extension). PHPIniDir i spune lui PHP (de data asta modulului PHP) unde
i gsete ierul de congurare php.ini, aa cum variabila de mediu PHPRC pe care am setat-o anterior
i spune acelai lucru SAPI-ului CLI (adic lui php.exe).
Acel bloc condiional35 IfModule veric dac apache are modulul dir, i dac da, seteaz resursa
de start corespunztoare root-ului (atunci cnd este accesat / al unui director, aa cum ai vzut n
capitolul anterior) ecrui director. Fiierele sunt listate dup ordinea prioritii, dac primul nu este
gsit, apache va ncerca s-l deserveasc pe al doilea.

O alt directiv important din httpd.conf este DocumentRoot. Acesta i spune lui apache de
unde s deserveasc iere. n mod standard, acest director se numete htdocs hypertext
documents.

Acum c avem totul setat, restarteaz daemonul httpd, n caz c e pornit, pentru a prelua toate
schimbrile din httpd.conf i ierele incluse de acesta. Ar trebuit s-i dm restart i dac am
modicat conguraia php din php.ini.
Pentru a verica instalarea i congurarea lui PHP ca modul apache, creaz un nou ier i salveaz-l
ca C:\webdev\apache\htdocs\info.php . Apoi introdu urmtorul text, numit i cod surs (n limbajul
PHP):
Listing 1.1: phpinfo() furnizeaz toate informaiile despre instalarea PHP curent
1
2

<?php
phpinfo ();

i salveaz-l.
Acum intr pe adresa http://localhost/info.php. Ar trebui s vezi ceva similar cu Figura 1.14.
Felicitri, acum ai PHP instalat i poi nva programare, e folosindu-l pentru programare web ca
modul apache, e folosindu-l ca limbaj de scripting universal folosind SAPI-ul CLI (programul php.exe).
SAPI-urile exist tocmai pentru a uura integrarea lui PHP n toate aceste medii: pentru web putem
folosi un SAPI specic daemonului folosit, de exemplu pentru apache avem SAPI-ul php5apache2_2.dll.
Acest ier DLL reprezint ns doar interfaa (SAPI-ul, aa cum i spune i numele de interface) de
comunicare dintre apache i adevratul PHP.
Pe acelai calapod, php.exe reprezint interfaa de comunicare dintre promptul ms-dos (sau shell,
ntr-un sistem *NIX) i acelai adevrat PHP ca i n cazul apache. Altfel spus, ambele, att php.exe,
ct i php5apache2_2.dll sunt dou SAPI-uri, ecare destinate integrrii lui PHP n mediile lor specice
de execuie a scripturilor PHP.
n capitolul urmtor ne vom uita mai ndeaproape la limbajul PHP.

34

http://en.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions
Se numete condiional deoarece ceea ce se a n interiorul su este inclus doar dac condiia este adevrat, numele
nsui coninnd If.
35

26

Dezvoltare web cu PHP

1.4. INSTALAREA MEDIULUI DE DEZVOLTARE

Figura 1.14: Informaii aate de un apel la phpinfo()

27

Capitolul

Controlul uxului de execuie1 i de date2


nelegerea uxului de execuie este primordial n crearea de aplicaii care fac mai mult dect simple
ari care iau decizii i i fac site-ul dinamic. Indiferent de ct de simpl sau ct de complex va
aplicaia ta, indiferent dac vei folosi baze de date sau simple iere, cu siguran vei folosi uxul de
execuie pentru a controla uxul de date. Acest capitol te introduce n lumea datelor, iar apoi i arat
cum s le manipulezi.

O altfel de remprosptare
Vreau s stabilesc nite lucruri care probabil nu sunt evidente pentru tine, sau asupra crora nu ai
insistat prea mult cnd ai nceput s nvei s creezi site-uri statice cu HTML, eventual cu CSS sau poate
chiar cu interaciune n interiorul browserului cu JavaScript.
HTML este un limbaj de formatare (en. markup language). Cu el nu controlezi ceva, nu iei decizii, deci
nu este un limbaj de programare. n HTML doar structurezi un document. n mod ideal l structurezi
semantic (semantic HTML), pentru a putea interpretat mai bine de motoarele de cutare web (en.
search engine).
Exist multe formate de iere, i chiar n capitolul anterior ai lucrat cu dou astfel de formate
formatul de congurare specic apache, i protocolul HTTP. Dac i aminteti, i-am explicat pe rnd ce
nseamn directive precum Include. Semnicaia acestor directive, sau general spus, semnicaia oricrei
entiti specice unui limbaj (e el de markup HTML, de congurare httpd.conf, de programare
PHP, sau un protocol de comunicare HTTP) constituie semantica acelui limbaj.
Semantica unui anumit construct al unui limbaj (de orice natur ar el) este strns legat de contextul
n care se a acel construct. De exemplu, pentru a cere o resurs cu HTTP, am vzut c poi ncepe
cererea cu GET, urmat de o cale absolut (care ncepe cu /) din cadrul Host-ului n cauz. Calea
respectiv are semnicaia pe care o vrem doar n contextul lui GET, ca dovad c atunci cnd vedem
ci de genul /script.php pe site-uri web, acestea nu sunt interpretate automat ca parametri GET, i
deci browserul nostru nu este redirecionat ctre acele pagini.
Contextul a ceva nseamn n ce punem acel ceva pentru a avea o anumit semantic. De exemplu,
sarea pus n contextul gtitului are semantica de condiment, dar dac o pui pe o ran, are semantica de
ceva care provoac durere. Cu alte cuvinte, context nseamn circumstane sau mediul nconjurtor.
Analog, HTTP/1.1 are semantica de protocolul i versiunea folosit n contextul request line-ului
HTTP al unui request HTTP.
1
2

en. execution ow
en. data ow

28

Dezvoltare web cu PHP

2.1. O ALTFEL DE REMPROSPTARE

ntrebri de sintez**

ns i GET nsui are semnicaia pe care ai ntlnit-o n capitolul trecut doar ntr-un anumit context
semantic.
1. Care este acest context semantic?
2. n ce context semantic are semantica ntlnit constructul Include?
3. n ce context semantic are sens comunicarea n limbajul (n protocolul) HTTP?
Determin contextul semantic n care urmtoarele constructe au semantica pe care o intuieti ca
cunosctor al limbajului HTML:
4. <td>
5. <tr>
6. <body>
7. <html>
8. href

Dac ai avut diculti majore la rspunderea ntrebrilor de sintez, te rog ia atitudine. n


primul rnd, plec de la premiza c citeti cu atenie, i c reii tot ce-i povestesc. Toate
noiunile pe care le introduc, le introduc pentru c astfel voi putea explica lucruri destul de
complicate mai trziu, pe baza celor spuse aici. Asta i va permite s tii multe nvnd ct
mai puin. Dezavantajul este c va trebui s i concentrat la ce citeti, i s sintetizezi singur
mult. Sinteza aceasta este un exerciiu perfect pentru tine ca viitor programator, deoarece
atunci cnd vei programa vei confruntat cu aceast nevoie de a sintetiza lucruri. Metoda
mea de predare, dei dur, te pregtete foarte bine pentru cariera ta de programator. Deci
dac simi c nu eti stpn pe ce ai nvat pn acum despre reelistic i despre semantic,
recitete acum, pn nu te pierzi denitiv. Cnd reciteti, urmeaz link-urile menionate dup
cum am spus n capitolul Introducere, acestea nu sunt lectur opional.

Pe lng semantic, un limbaj mai are i o sintax. Regulile sintactice ale limbajelor sunt necesare
pentru a crea contextul semantic n care vor exista constructele acelui limbaj.
Vreau s ilustrez asta cu un exemplu: n protocolul HTTP, GET trebuie s e separat de cale printrun spaiu. Asta este o regul sintactic a limbajului, standardizat prin RFC-uri, ns practic separatorul
ar putea orice altceva. ns un separator trebuie s e acolo, altfel calculatorul (browser-ul sau daemonul) nu ar putea decide unde ncepe cuvntul cheie GET, unde se termin, i unde ncepe calea ctre
resursa pe care o dorim. Aceste reguli sintactice permit programelor precum daemon-uri i clieni HTTP
s parseze (s neleag) datele comunicate reciproc.
Exist multe posibiliti de a exprima sintaxa unui limbaj, ns acestea sunt mult prea complexe
pentru noi. ns exist un standard nescris pentru a specica sintaxa unor constructe simple, ntr-o
singur linie. Ea se leag de necesitatea unui anumit parametru.
De exemplu, sintaxa constructului GET ar putea :
'GET ' <RESOURCE> ' HTTP/1.1'
RESOURCE este pus ntre < i >, ceea ce denot c este un parametru necesar, care trebuie specicat.
GET (inclusiv spaiul) i HTTP/1.1 sunt puse ntre apostrofuri pentru a arta c sunt lucruri ce
trebuie scrise exact aa cum sunt. RESOURCE este numele simbolic al parametrului, pe care l putem
refolosi n documentaia limbajului (n cazul nostru, documentarea limbajului HTTP, sau mai bine spus,
a unei cereri HTTP de baz).
Pentru a specica c un parametru e opional, l punem ntre [ i ]. Astfel, sintaxa unei cereri HTTP
ca cea pe care am fcut-o n capitolul anterior, mpreun cu descrierea ei, ar putea arta astfel:
29

Dezvoltare web cu PHP

2.1. O ALTFEL DE REMPROSPTARE

'GET ' <resource> ' HTTP/' <version> <enter>


['Host: ' <name enter> ]<enter>
- resource = the absolute path to the resource
- version = the version of the HTTP protocol used;
currently only 1.0 and 1.1 are supported
- name
= the hostname
- enter
= press return once
Pe lng lucrurile evidente pe care ni le spune aceast specicaie sintactic, ne mai spune i un lucru
care probabil i-a scpat: cmpul Host este opional, dar dac l specicm, atunci trebuie s specicm
i parametrul name, i s i apsm o dat enter.
Cu siguran ai realizat c astfel de reguli pot incluse una n alta, crend reguli destul de complexe.
Un limbaj precum cel de mai sus, care folosete <,>,[,] pentru a specica un alt limbaj se numete
un metalimbaj. Meta nseamn care descrie - un limbaj care descrie limbajul.
Cel mai probabil ai ntlnit deja tag-ul HTML <meta>, de aici i provine numele. Diferena este c
<meta> nu se refer la limbaj (HTML n cazul de fa), ci la informaii. Ceea ce <meta> ne spune despre
documentul HTML n care se a se numesc metainformaii - informaii care descriu informaiile din
documentul curent.
Probabil ai folosit deja un forum pe web. Probabil c acel forum i spunea la un moment dat c
autorul unei intrri (al unui topic sau thread) se numete Xulescu. Ei bine, n timp ce intrarea propriuzis constituie informaia, numele autorului este o metainformaie (en. metadata) - o informaie despre
informaie.

La ce i folosete aceast cunoatere despre metadate, metalimbaje, sintax i semantic? n


primul rnd, ai nvat primul cel mai important lucru pragmatic din viitoarea ta carier de
programator: s citeti manualul (PHP sau orice altceva) chiar dac nc nu eti contient de
asta.
n al doilea rnd, meta-ceva-urile te vor nsoi n toate aplicaiile pe care le vei programa. Uitte la toate aplicaiile pe care le foloseti, vei vedea c toate au nite metadate. Singurul lucru
care te-ar mpiedica s vezi asta este c datele i metadatele se ntretaie att de mult nct e
greu s le identici pe ecare.
i n al treilea rnd, pentru a te pregti pentru exerciiile urmtoare care au menirea de a te
dezghea la minte puin, deoarece, din pcate, nu tiu nimic despre cititorul meu, ns trebuie
s m asigur cumva c este pe aceeai lungime de und ca mine, ceea ce-i permite s asimileze
ct mai ecient cunoaterea prezentat n continuare, fr risip de cuvinte.

Fie regula sintactic

Reguli sintactice*

[A] A [A A] [A [A <B>]] <C>

Partea I
Care
1.
2.
3.
4.
5.

dintre urmtoarele inputuri o respect?


AABC
AAAAC
AC
AAAC
AAABC
30

Dezvoltare web cu PHP

2.1. O ALTFEL DE REMPROSPTARE

Partea II
Detaeaz-te de nivelul abstract al acestei reguli sintactice, i f o armaie pragmatic despre B. Armaia
ncepe aa: ntr-un input valid, B este mereu
Metalimbajul prezentat nu este btut n cuie. n primul rnd, caracterele speciale ale limbajului
<,>,[,] i pot schimbate n orice, atta timp ct documentezi aceste schimbri aduse de tine.
Deasemenea, nu este dect un standard nescris, i l poi extinde n ce fel ai nevoie. Din nou,
important este doar s documentezi extensiile aduse metalimbajului astfel nct ceilali programatori
s i neleag specicaia limbajului pe care l descrii cu ajutorul acelei extensii proprii a metalimbajului.
De exemplu, s zicem c vrem s introducem un nou construct n acest metalimbaj care s nsemne
simbolul din stnga mea poate aprea o dat sau de mai multe ori, i ne decidem s folosim simbolul +
pentru asta.
Astfel o regul de genul:
<FOO+> [BAR+]
S-ar putea citi ca: Unul sau mai muli FOO urmat de zero sau mai muli BAR. Un astfel de simbol precum
+ se numete cuanticator. Ar la ndemn s stabilim, n documentaia extensiei noastre adus
metalimbajului, c + poate cuantica orice entitate din stnga sa, inclusiv o grupare <> sau [].
Documentaia ar suna aa:
+ = repeat the entity on its left once or multiple times (a quantifier)
the entity can be any SYMBOL, <required parameter> or
[optional parameter]
Iar exemplul de mai sus, n care vrem ca FOO i BAR s e separai de un eventual spaiu, ar deveni:
<FOO ' '>+ [BAR ' ']+
Pn acum deniiile noastre sintactice se limitau doar la o singur regul (o singur linie), ns
am putea introduce constructe n metalimbaj care ne-ar da voie s atribuim nume acestor reguli, i s
refolosim acele nume n deniiile altor reguli sintactice, crend astfel interdependene ntre reguli, i deci
crea specicaiile unor limbaje foarte complexe.

Majoritatea limbajelor de programare, inclusiv PHP, sunt denite n astfel de limbaje.

Sintaxa HTML***

Acum hai s aplicm ce am nvat asupra limbajului HTML. n HTML avem tag-uri (ex. <html>)
care au atribute i valori.
1. Creaz o specicaie sintactic a limbajului HTML folosind doar cuvintele cheie TAG,
ATTRIBUTE i VALUE, care combinate cu [] i <> s reecte ct mai corect sintaxa limbajului.
Specicaia trebuie s valideze orice text HTML valid. Un exemplu de input ar :
<form method="get">
<checkbox name="hello" checked>
<input type="submit">
</form>
Note:
Regula creat nu trebuie s ia n calcul sintaxa specic XHTML (n care de exemplu <img> ar
greit, doar <img /> este valid).

31

Dezvoltare web cu PHP

2.2. OUTPUT SIMPLU

Se pleac de la premiza c inputul este cel mai curat HTML posibil, c sunt folosite pentru a
delimita valorile atributelor (dac acestea exist), c nu e mai mult de un spaiu acolo unde e nevoie
de spaiu, .a.m.d. Pe scurt: folosete-i intuiia pentru a decide ce nseamn cel mai curat HTML
posibil.
Deoarece caracterele < i > au o semnicaie special n limbajul HTML, pe care ncerci s-l descrii
sintactic folosind printre altele i caracterele < i > nsei, va trebui s le pui ntre apostrofuri, pentru
a face diferena ntre <,> care ne spun n metalimbajul nostru c acel parametru este necesar, i
< sau > care ne spun c ne referim la caracterul < respectiv > n limbajul pe care vrem s-l
descriem (adic HTML nsui).
Va trebui s extinzi metalimbajul (nu uita s i documentezi extensiile aduse) pentru a ajunge la o
rezolvare ct mai corect i complet
Exerciiul este destul de dicil. ncearc s te apropii ct mai mult de soluia cea mai corect i
complet.

Output simplu
La sfritul capitolului anterior, ai fcut cunotin cu primul tu cod PHP:
1
2

<?php
phpinfo ();

Prima linie marcheaz nceputul procesrii PHP. Ce se a naintea <?php este trimis aa cum este
ctre client. Hai s testm. Scrie ceva n tagul <h1> nainte de nceputul procesrii PHP i vezi ce iese:
1
2
3

<h1 >Hello </h1 >


<?php
phpinfo ();

PHP genereaz prea mult cod HTML pentru gusturile noastre simpliste, deci f cunotin cu un
cuvnt cheie n PHP: echo. Sintaxa general este:
echo <EXPR>;
unde EXPR trebuie s e o expresie care evaluat, se reduce la o valoare.

Nu te speria dac nu nelegi totul, voi reveni asupra subiectului. Deocamdat urmeaz pur
i simplu paii prezentai de mine, respectnd sintaxa. Simte-te liber s faci modicri, s
experimentezi. Dac faci ceva ce genereaz o avertizare sau o eroare nu te impacienta, citete-o
cu atenie, ncearc s o nelegi, i cere lmuriri comunitii e prin IRC, e prin mailing list-ul
proiectului.

Hai s-l nvm pe PHP s ne salute. n notepad++ creaz un nou ier i salveaz-l ca salut.php
n htdocs, apoi introdu codul:
1
2

<?php
echo'Salut Flavius ';

Acum f cu telnet o cerere HTTP, s vezi exact ce se ntmpl atunci cnd interpreterul PHP execut
acel cod:
GET /salut.php HTTP/1.1
Host: localhost
32

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

Ce observm? Exact! Observm c nu vedem nici urm de cod PHP, vedem doar outputul generat de
el. Nu tu <?php, nu tu echo. Asta ne demonstreaz c PHP ne-a procesat scriptul, script care a generat
output. Dac scriptul nu ar generat output, response body-ul HTTP ar fost gol.
n al doilea rnd, http response body nu conine date n format HTML. De ce? Simplu, deoarece nu
i-ai spus niciunde s genereze nimic ce ar putea arta a HTML. Cum facem asta? O posibilitate ar
urmtoarea:
<?php
echo'<html ><body >';
echo'Salut Flavius ';
echo '</body ></html >';

1
2
3
4

Concluzia pe care o tragem este c PHP habar n-are ce este HTML. De ce? Dup cum am spus atunci
cnd ai instalat CLI-ul PHP (numit php.exe), PHP este un limbaj de scripting general. De fapt nu este
legat n niciun mod de HTML sau de site-uri. Este doar felul n care l folosim noi i majoritatea restului
lumii. De fapt, PHP poate genera orice, imagini, documente, animaii (ash). Chiar nu eti restrns la
HTML, dar nici nu te ajut n acest sens trebuie s scrii manual codul HTML, dup cum ai vzut mai
sus.
Vei vedea ns c i pune la dispoziie constructe care nlesnesc generarea de HTML de exemplu
poi genera o galerie de imagini aate ntr-un anumit director pe server, fr s trebuiasc s tii dinainte
numele ierelor.
Totui exemplul nostru anterior nu prea are sens nu este nimic dinamic n el. L-am putea rescrie
la fel de bine doar n HTML static, ns deoarece vreau s demonstrez altceva, voi genera totui mesajul
de salut cu PHP:
<html >
<body >
<?php
echo'Salut Flavius ';
?>
</body >
</html >

1
2
3
4
5
6
7

Observi c pentru a termina procesarea PHP i a aa din nou totul aa cum este (en. unparsed) se
folosete ?>. n acest mod poi porni i opri procesarea PHP de oricte ori doreti n acelai ier. La
sfritul ierului procesarea este terminat automat, de aceea n exemplele anterioare nu a fost nevoie
de ?>.

Mai observ i cum mi-am fcut codul uor de citit indentndu-l (en. to indent), adic am
aliniat deschiderea ecrui tag HTML cu tag-ul de nchidere corespunztor, fcndu-mi codul
lizibil. Pentru codul nostru surs minuscul nu prea conteaz, ns diferena de mentenabilitate
va vizibil cnd ierele vor avea sute sau mii de linii de cod (LOCs en. lines of code). Deci
obinuiete-te s indentezi codul apsnd tasta TAB pentru ecare nou nivel de indentare
necesar.

Din acest punct nainte scopul nostru este s nvm PHP, nu s generm cod HTML valid, deci
nu ne vom mai obosi s decorm textul generat cu html sau body. ns nu uita c ntr-o pagin HTML
normal, valid, i asta trebuie fcut, eventual punnd i un doctype 3 , altfel browserul intr n quirks
mode.

Folosirea variabilelor
nainte de a trece la noiuni noi, trebuie s revenim asupra exemplului nostru cu cteva completri:
3

document type declaration

33

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

<?php
echo'Salut Flavius ';

1
2

tim deja c echo este un cuvnt cheie care genereaz output pe baza primului su parametru. Sper c
ai intuit deja c ecare instruciune trebuie separat de urmtoarea prin ;.
ns ce este Salut Flavius? Este o valoare n primul rnd, pentru c i-o putem pasa lui echo. n al
doilea rnd, este o constant, deoarece nu se modic. La ecare interpretare a scriptului, output-ul va
acelai. Sumarizat: este o valoare constant.
Pe lng faptul c este o valoare constant, mai este i un ir de caractere (en. string). Acesta este
motivul pentru care am pus mesajul ntre apostrofuri altfel PHP ar ncercat s interpreteze Salut i
Flavius ca constructe ale limbajului, care evident nu exist.

Corect terminologic spunem deci c Salut Flavius este un string constant sau mai pe larg o
valoare constant de tip string.

Deci ncearc! F-l pe PHP s genereze erori:


<?php
echoSalut Flavius ;

1
2

Mesajul de eroare ne-ar putea prea confuz:


Parse error: syntax error, unexpected T_STRING, expecting ',' or ';'
Ceea ce se ntmpl este urmtorul lucru: PHP citete echo, i deoarece a citit i a recunoscut
instruciunea echo, intr n contextul semantic n care se ateapt ca urmtorul lucru s e o valoare,
ns nu gsete una, ci ntlnete Salut, pe care nu-l recunoate4 ca i construct al limbajului. De aceea
ne spune c nu se ateapt s vad T_STRING-ul Salut.
Dar stai puin, de ce l numete T_STRING, dar nu l accept ca string? Pentru a nelege
asta, trebuie s priveti puin lucrurile din perspectiva parserului PHP. Codul surs pe care l scriem n
limbajul PHP este folosit ca input pentru parser. Acest input scris de noi este citit de PHP ca string, ca
un ir de caractere. Din acest motiv PHP ne spune foarte corect c nu se ateapt s vad acel string
acolo, ci altceva.

Pentru PHP, codul scris de noi este un simplu text.

Hai s vedem ce ar genera PHP dac nu s-ar atepta s vad un string din perspectiva noastr:
<?php
echo'Salut ''Flavius ';

1
2

ne zice Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING.


Ce nvei din asta? n primul rnd, nvei c mesajele de eroare, dei nedorite, ofer informaii
preioase despre ce s-a ntmplat. Din proprie experien pot spune c vederea unui mesaj de eroare
sau avertizare e ca o mn cereasc, reversul medaliei ind mult mai frustrant: s nu vezi o eroare, dar
codul nici s nu funcioneze aa cum i imaginezi c ar trebui s funcioneze sau mai ru, s nu aeze
nimic, lsndu-te n ntuneric complet. Deci fericit cnd PHP i spune ce ai greit, caut s nelegi
ce-i spune, i apoi repar-i greeala.
Pe lng stringuri, mai exist i alte tipuri de valori constante. PHP nelege numere ntregi (en.
integers), de exemplu 42,5 numere cu virgul (en, oating point numbers sau scurt oats), unde partea
zecimal e separat de partea ntreag prin punct, de ex 3.1415, i alte lucruri asupra crora vom reveni.
Hai s ne uitm la un exemplu:
<?php
echo'Salut 00 ';

1
2
4
5

De fapt, parserul se blocheaz la Flavius, ns ca s explic asta cum trebuie, ar trebuit s introdus deja constantele
Sunt curios cnd va veni cineva s-mi spun de ce am ales 42 :-)

34

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

echo7;
echo '.PIeste~';
echo 3.1415;

3
4
5

2.3.1 Variabile i tipuri de date elementare


Toate bune i frumoase cu lucrurile cu care ai fcut cunotin pn acum, ns ele nu te-au ajutat
s creezi ceva dinamic.
Deci hai s facem un pas napoi i s ne gndim ce nseamn i ce implic o eventual dinamicitate.
Pentru a dinamic, o pagin trebuie s e capabil s primeasc date de intrare (input), pentru a
genera date de ieire (output) pe baza acestora.
De exemplu, s zicem c vrem s facem o pagin care n loc s aeze mereu Salut Flavius, aeaz
Salut <nume>. Acest input (numele) trebuie salvat undeva, altfel nu avem acces la el. Bine ai venit
n lumea variabilelor.
O variabil are trei caracteristici
1. un nume sau identicator
2. o valoare pe care o ine
3. tipul de date (en. datatype) al valorii6 precum string, int sau oat pe care le-ai cunoscut mai
devreme
Identicatorul variabilelor ncepe mereu cu $, primul caracter dup el trebuie s e o liter sau
underscore (_), iar urmtoarele caractere pot litere, cifre, sau underscore. Nu exist o limit n
lungimea identicatorului, i nici restricii privind numirea lor. Exist ns reguli nescrise pe care le vei
ntlni mai trziu, ct i variabile pe care PHP le creaz automat pentru tine.
Valoarea unei variabile poate orice bucat de informaie ce poate salvat.
Tipul de date al valorii poate unul din cele trei prezentate mai sus, sau altele pe care le vom cunoate
n acest capitol i n capitolele urmtoare.
Dup cum am spus, echo aeaz valoarea unei expresii. Aceast valoare poate una constant,
precum n exemplele anterioare, ns poate i o variabil. Exemplu:
<?php
echo$nume ;

1
2

PHP ne va ateniona cu o noticare c am ncercat s accesm o variabil nedenit. Pentru a deni o


variabil trebuie s-i atribuim o valoare mai nti, iar asta o facem cu operatorul de atribuire =. Putem
spune i c am salvat valoarea X n variabila Y. Exemplu:
<?php
$nume ='Flavius ';
echo'Salut ';
echo$nume ;

1
2
3
4

echo nu adaug automat spaii niciunde. Este responsabilitatea noastr s o facem. PHP chiar
nu are noiunea de cuvinte. Pentru el, un ir de caractere este un ir de caractere i att.

n cazul de fa, variabila $nume nu prea i are rostul, deoarece o folosim o singur dat. ns
imagineaz-i c ai un script lung, i vrei s refoloseti acel nume n diferite locuri n cadrul generrii de
output. Variabilele sunt ideale pentru acest lucru, deoarece nu trebuie dect s schimbi valoarea ntr-un
loc, iar schimbarea va preluat n ntregul script:
6

mai spunem colocvial i tipul de date al variabilei ns n PHP tipul de date este inerent valorii vom reveni mai trziu
asupra acestui aspect

35

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

<?php
$nume ='Flavius ';
echo'Salut ';
echo$nume ;
echo'<br >';
echo$nume ;
echo',cefaci ?';

1
2
3
4
5
6
7

Felicitri, ai creat primul tu script care reutilizeaz variabile.

2.3.2 Operaii cu string, int, oat


Cu aceste tipuri de date se pot face operaii. n primul rnd, stringurile pot concatenate, indiferent
dac sunt salvate n variabile sau provin din valori constante. A concatena nseamn a lipi un string de
urmtorul, pentru a forma un nou string. Exemple:
<?php
$a='Salut '.'Flavius ';
echo$a;
echo'<br >';
$a=$a.'Aspra ';
echo$a;

1
2
3
4
5
6

Linia 2 face urmtorul lucru: mai nti concateneaz cele dou valori constante Salut i Flavius,
operaie n urma creia rezult valoarea intermediar Salut Flavius. i poi imagina c aceast valoare
st acum de partea dreapt a operatorului de atribuire. Iar deoarece avem o atribuire, aceast valoare
intermediar este salvat n variabila $a.
Linia 3 aeaz valoarea salvat n variabila $a.
Ne-am putut folosi de acea valoare intermediar de pe linia 2 aand-o direct:
<?php
echo'Salut '.'Flavius ';

1
2

Aici valoarea intermediar care rezult n urma concatenrii celor dou stringuri constante este pasat
direct (ca o nou valoare) instruciunii echo.
Dup cum ai observat pe linia 2, operaia de atribuire este interpretat de PHP de la dreapta la
stnga. Mai nti sunt fcute rnd pe rnd operaiile din partea dreapt a atribuirii, apoi valoarea
rezultat este salvat n variabila aat n stnga atribuirii. Datorit acestei ordini spunem c operaia
de atribuire (en. assignment) este right-associative.
Linia 5: Datorit asociativitii de dreapta a operaiei de atribuire, ntr-o atribuire putem folosi
o variabil precum $a n partea dreapt, genera o valoare temporar pe care o atribuim tot variabilei
$a, suprascriind valoarea sa iniial. Dac am tiut c mai avem nevoie de nume ca valoare de sine
stttoare, pe linia 5 ar trebuit s introducem o nou variabil creia s-i atribuim noua valoare, astfel
nct s nu pierdem valoarea iniial a lui $a. ns n cazul nostru, linia 5 este extrem de curat, deoarece
nu introduce o nou variabil n mod inutil.
S revenim la sintax i la semantic. Sintaxa lui echo este:
echo <EXPR>;
Iar a operaiei de concatenare este:
<expr1> . <expr2>
<expr1> i <expr2> pot orice fel de expresii, e ele valori constante, sau variabile deoarece variabilele
au i ele o valoare pe care o car cu ele. n urma operaiei de concatenare rezult o valoare intermediar.
Chiar dac aceasta e invizibil (deoarece PHP o creaz n mod transparent pentru noi), ea este tot o
valoare ca oricare alta, deci poate pus oriunde PHP ne las s punem o expresie.
Dar stai puin, operaia de concatenare nsi accept dou expresii! Consecina? Putem concatena
acele valori intermediare, transparente, ntr-un lan7 :
7

n matematic spunem c abordm problema inductiv.

36

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

<valoare1> . <valoare2> . <valoare3> . <valoareN>


n astfel de cazuri, <valoare1> este concatenat cu <valoare2> i rezult o valoare intermediar,
transparent, care este apoi concatenat cu <valoare3>, i tot aa. Exemplu:
1
2
3

<?php
$nume ='Flavius ';
echo'Salut '. $nume . '.Cefaci ,'. $nume . '?';

Despre limbajul PHP se spune c este dynamically typed. Asta nseamn c poate (n limitele bunului
sim), s converteasc automat o valoare de un tip, ntr-o alt valoare de alt tip, care e ct mai apropiat
de valorea iniial. Aa se face c dei operatorul de concatenare accept doar doi parametri de tip string,
putem totui concatena i numere. PHP va crea ns nc o valoare intermediar cu reprezentarea valorii
iniiale ca string. Un exemplu:
1
2
3

<?php
$nume =7;
echo'Salut 00'. $nume . '.Cefaci ,00'.$nume . '?';

ncearc s evii a-l fora pe PHP s trebuiasc s converteasc un numr ntr-un string,
deoarece operaia asta consum resurse inutil. n schimb folosete sintaxa alternativ a lui
echo cu care vei face cunotin n continuare.

Primul cod propriu

Continu codul urmtor astfel nct s aeze


Valoarea lui PI este 3.1415.
1
2

<?php
$pi= 3.1415

Exist o sintax alternativ pentru echo, care ne permite s am valori constante amestecate cu
valori variabile fr a mai crea valori intermediare, deci PHP poate executa scriptul mai rapid i cu
consum mai mic de memorie. Pentru asta punem virgul ntre valori:
1
2

<?php
echo'Salut ', $nume ;

Asta nseamn practic c echo va apelat asupra ecrui parametru din list. Atenie: diferenele
se pot vedea doar atunci cnd lucrezi cu cantiti mari de informaie.

Sintaxa alternativ pentru echo*

De cte ori va apelat echo n codul urmtor?


1
2

<?php
echo'Salut ','Homer '.'Simpson .','Ce'.'faci ?';

1. o dat
2. de trei ori
3. de cinci ori

37

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

Determinarea uxului de execuie ntr-un exemplu simplu**

Explic cum crezi c execut PHP urmtoarea linie, ct mai concret posibil, aa cum ai vzut n
explicaiile anterioare.
Listing 2.1: echoing an assignment
1

echo$foo='hello world ';

2.3.3 Operaii matematice


PHP tie toate cele patru operaii aritmetice: + pentru adunare, - scdere, * nmulire i /
pentru mprire. tie i c nmulirea i mprirea sunt de gradul doi, iar dac ai nevoie de alt
ordine a operaiilor poi folosi paranteze rotunde pentru grupare. Parantezele creaz deasemenea valori
intermediare, ca i operatorul de concatenare.
Rezultatele pot atribuite variabilelor, deoarece sunt tot valori, pot aate, sau chiar concatenate.
Nu trebuie dect s pui cap la cap ce ai nvat pn acum i s-i lai imaginaia s zboare. Un exemplu
cu operaii matematice de la simple la complexe:
Listing 2.2: Operaii matematice
1
2
3
4
5
6
7
8
9
10
11

<?php
/**
* variabile
*r-raza cercului
*a- lungimea laturii patratului
*m,n- lungimea si latimea dreptunghiului
* output :
*Ariaunuicercderazar=10este314.15 <br >
* Diametrul saueste20<br >
* Dreptunghiul cu laturile 712are perimetrul 38
*/

12
13
14
15
16
17

$r=10;
$pi= 3.1415;
$a=$pi;
$m=7;
$n=12;

18
19
20
21
22

//------- calcule
$c_area =$pi*$r*$r;
$r_area =$m*$n;
$r_perim =2*($m+$n);

23
24
25
26
27

//------- afisare
echo'Ariaunuicercderazar=',$r ,'este',$c_area ,'<br >';
echo'Diametrul saueste',$r*2,'<br >';
echo'Dreptunghiul cu laturile ',$m ,'',$n ,'are perimetrul ', $r_perim ;

Majoritatea lucrurilor ar trebui s-i e cunoscute. Liniile 2-11, 19 i 24 conin aa-numite comentarii.
Exist dou tipuri de comentarii, cele care se ntind pe mai multe linii i ncep cu /* i se termin cu
*/. Al doilea tip ncepe cu // i se termin la sfritul liniei.
Menirea unui comentariu este s documenteze sau s marcheze anumite lucruri n cod. Cnd
scripturile tale vor deveni foarte complexe, vei vrea s le documentezi comentndu-le, astfel nct si poi aminti uor ce face codul i de ce o face.

Comentariile sunt ignorate de PHP. Ele conin practic metadate despre codul nsui, utile doar
programatorului.
38

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

ncearc s nu pui comentarii stupide, precum:

1
2
3

<?php
// afiseaza 'Hello world ';
echo'Hello world ';

Las codul s vorbeasc de la sine, pe ct posibil. Documenteaz variabilele introduse i felul n


care sunt folosite. Documenteaz algoritmii compleci. ncearc s-i imaginezi ce nu ar nelege
din prima cineva care i-ar vedea codul pentru prima oar i documenteaz acele lucruri.

Asteriscurile de pe liniile 3-10 nu sunt necesare, ns este un standard mai mult sau mai puin
nescris s i formatezi n acest fel comentariile care documenteaz codul. Standardul vine din
lumea java, unde acestea se numesc javadocs8 . i n PHP, ca i n java, exist scule care extrag
informaiile din docblocks i genereaz automat documentaie.
n capitolele urmtoare vei face cunotin cu astfel de scule. Deocamdat obinuiete-te s i
documentezi codul cum trebuie, chiar dac scripturile scrise de tine sunt mici i nu simi nevoia
de a le documenta. Scrierea documentaiei te ajut s i xezi mai bine lucrurile nvate.

Comentariile mai pot folosite de programator i ca un mijloc rapid de a testa diferite funcionaliti.
S zicem c ai dou soluii posibile pentru rezolvarea unei anumite probleme. O poi comenta pe prima,
i o lsa doar pe a doua s e executat. De exemplu:
<?php
// echo 1+4*3;
echo(1+4) *3;// calculeaza corect ,cu paranteze

1
2
3

Pentru a reprezenta numere negative, ntregi (int) sau cu virgul (oat), nu trebuie dect s pui un
minus n faa lor. De exemplu:
<?php
echo -4+ -3;

1
2

Deseori vei n situaia de a vrea s faci o operaie matematic asupra valorii unei variabile, i s
salvezi rezultatul n aceeai variabil. Pentru astfel de cazuri, poi combina operatorii matematici +,-,*,/
cu operatorul de atribuire. Cteva exemple:
<?php
$a=7;
echo'aeste',$a ,'<br >';
$a+=2;// saupelung$a=$a+2;
echo'a+=2face',$a ,'<br >';
$a/= -3;//$a=$a/3;
echo'a/= -3este',$a ,'<br >';

1
2
3
4
5
6
7

De fapt, poi combina chiar i operatorul de concatenare cu atribuirea:


<?php
$a='Hello ';
$a.='world ';

1
2
3

http://en.wikipedia.org/wiki/Javadoc

39

Dezvoltare web cu PHP

2.3. FOLOSIREA VARIABILELOR

Lips output

De ce codul urmtor nu aeaz nimic?


1
2
3

<?php
$a='Hello ';
$a.='world ';

Mai exist nc un operator matematic foarte interesant numit modulo, cu simbolul %. Operaia
modulo are ca rezultat restul mpririi primului operand la al doilea. Exemplu:
1
2

<?php
echo11%3;

Este interesant deoarece cu el putem determina dac un numr este multiplul unui alt numr.
Liniile 20-22 din exemplul 2.2 introduc variabile intermediare noi n care salvm valorile unor calcule.
Asta nu este neaprat greit, ns noi variabile trebuie introduse doar atunci cnd tii c vei avea de
gnd s refoloseti (de cel puin dou ori) o valoare, sau cnd o valoare trebuie s se schimbe de-a lungul
execuiei scriptului, dinamic (cci asta spune nsui termenul de variabil). De exemplu, s zicem c
vrei s salui vizitatorul cu Bun dimineaa, Bun ziua sau Bun seara n funcie de ora actual
a Bucuretiului.
Deoarece noi folosim acele variabile intermediare $c_area, $r_area i $r_perim o singur dat, am
putea renuna la ele i am putea pasa rezultatele calculelor direct lui echo, fr a le mai salva n variabile.
Astfel, linia 25 ar deveni:
1

echo'Ariaunuicercderazar=',$r ,'este',$pi*$r*$r ,'<br >';

U
R

Inventeaz variabile noi doar atunci cnd ai nevoie de ele. Variabilele ocup memorie de lucru
i mnnc timp la procesare.
n plus, n unele cazuri, prea multe variabile i pot face scriptul greu de neles. ns acest
lucru este valabil i dac introduci prea puine variabile. Sfatul anterior rmne valabil i n
acest caz: gndete-te bine cnd i dac ai nevoie de o nou variabil, i introdu una nou n
mod responsabil.

Primul pas spre creativitate*


Partea I

Uit-te nc o dat pe exemplul 2.2 cu atenie, ncearc s-i impregnezi sintaxa i outputul, apoi
nchide cartea, scoate un creion i o foaie de hrtie i scrie un cod similar care s fac acelai lucru.
Poate un cod complet diferit, nu trebuie s e acelai, i nici variabilele nu trebuie numite la fel.
Funcionalitatea trebuie ns s e asemntoare!
Apoi transcrie codul de pe foaie ntr-un ier PHP i ruleaz-l. 99% din nceptori vor face greeli,
ceea ce e bine. Doar aa i se vor impregna n minte anumite lucruri.

Programarea pe hrtie este cea mai sntoas, mai ales pentru un nceptor. Te provoc s mi
urmezi sfatul, pentru c l dau din proprie experien.

Partea II
40

Dezvoltare web cu PHP

2.4. ALGORITMI I SCHEME LOGICE

Completeaz scriptul astfel nct s aeze i volumul cubului de latur $a.

Algoritmi i scheme logice


Un algoritm este un set de instruciuni bine denit care descrie pas cu pas ce trebuie fcut pentru a
rezolva o problem dat.
Atunci cnd scriem un cod PHP, textul pe care l scriem n ntregimea sa este descrierea unui algoritm.
Cum calculatoarele actuale sunt simple maini i nu dispun de inteligen, algoritmii pe care i
concepem trebuie s e foarte exaci, lipsii de ambiguiti.
i poi imagina c pn acum PHP executa instruciune cu instruciune scripturile noastre, ecare
instruciune ind separat de urmtoarea prin ;. Deoarece PHP executa toate instruciunile exact n
ordinea n care le citea, spunem c pn acum execuia a fost liniar.
Limbajul PHP ne pune la dispoziie constructe pentru a bifurca execuia. i poi imagina c, atunci
cnd PHP execut un cod, se plimb cu un fel de cursor pe deasupra textului. Folosind o astfel de
bifurcaie i-am putea spune dac o condiie C este adevrat, f X, dac nu (altfel) f Y sau la fel de
bine i-am putea spune atta timp ct condiia C este adevrat, f X.
Descrierile n cuvinte de mai sus dac ... atunci ... sau atta timp ct ... pot formalizate n
ceea ce numim limbaj pseudocod.
Limbajul pseudocod ne permite s descriem algoritmi folosind limba romn, aa cum am folosit
metalimbajul din seciunea trecut pentru a descrie sintaxa limbajului HTML.
Pseudocodul nu are o sintax strict, ns e bine s ne exprimm ct mai clar i punctual, fr
omisiuni.
De exemplu, un algoritm de autenticare ar putea specicat astfel:
daca parola este corecta
afiseaza 'autentificat '
altfel
afiseaza 'acces restrictionat '

1
2
3
4

ns acesta este incomplet! De unde vine acea parol pe care am menionat-o pe linia 1?
Calculatoarele sunt stupide, i la fel este i PHP. Va trebui s-i spunem mai nti c citim acea parol:
citeste parola
daca parola este corecta
afiseaza 'autentificat '
altfel
afiseaza 'acces restrictionat '

1
2
3
4
5

Sun stupid, probabil ar trebui s ne ateptm ca electronica din CPU s ghiceasc cumva ce vrem
de la ea. Deocamdat asta nu este posibil, n mare parte deoarece dispozitivele electronice, inclusiv un
CPU,9 nu sunt inteligente. Pn cnd nu va aprea inteligena articial, va trebui s ne resemnm
cu faptul c e responsabilitatea noastr de ine inteligente s gndim i s concepem algoritmi pentru
maini, pe care acestea s le urmeze pas cu pas.
Pe linia 2 a algoritmului anterior are loc o bifurcaie. La rulare, PHP ar decide dac parola este
corect, i dac da, va trece cu cursorul su de execuie prin linia 3, altfel va trece prin linia 5.
Te rog atent cum indent-area codului reect crei crri din aceast bifurcaie aparine ecare
din cele dou instruciuni aeaz.
S zicem c vrem s am Salut <autenticat|necunoscut>. Ce faci?, unde algoritmul decide pe
baza unui input parol ce s aeze, autenticat sau necunoscut, ns n ambele cazuri s e aat
Salut i . Ce faci?.
9

Central Processing Unit

41

Dezvoltare web cu PHP

2.4. ALGORITMI I SCHEME LOGICE

Un astfel de algoritm ar putea arta astfel:


1
2
3
4
5
6
7

citeste parola
afiseaza 'Salut '
daca parola este corecta
afiseaza 'autentificat '
altfel
afiseaza 'necunoscut '
afiseaza '.Cefaci?'

Liniile 1 i 2 vor executate liniar, iar la linia 3 bifurcm uxul de execuie. Dac parola citit este
corect, uxul de execuie va trece prin linia 4, altfel el va trece prin linia 6. Linia 7 ns nu se a ntr-o
bifurcaie, ci continu execuia liniar din care fac parte i liniile 1 i 2 i de fapt i 3.
Exact, i linia 3 face parte din execuia liniar, deoarece acea vericare este parola corect? va
executat de ecare dat.

Execuia liniar conine i vericarea condiiei*

De ce face parte i vericarea unei condiii din execuia liniar de dinainte i de dup dac?
Fluxul de execuie este constituit din locurile prin care plimbm acel cursor folosit de PHP pentru
a executa ecare instruciune. Acest ux este dinamic, se poate schimba la rularea scriptului, folosind
exact aceste constructe ale limbajului precum dac sau atta timp ct, constructe pe care le vom
cunoate n paginile viitoare.
Aa cum putem descrie un algoritm folosindu-ne doar de text, putem descrie un algoritm i prin
scheme grace. Aceste scheme grace se numesc scheme logice (en. owcharts).
Figura 2.1 este transpunerea ntr-o schem logic a algoritmului descris n pseudocodul anterior.
Regula de baz la interpretarea unei scheme logice este s urmezi n mod stupid sgeile, la fel ca i
coiotul nostru din gura 2.2.
O schem logic are doar un singur bloc BEGIN, i unul sau mai multe blocuri END. O schem
logic curat ar trebui s aib totui un singur bloc END ctre care conduc toate crrile de execuie
posibile.
Operaiile de input/output sunt puse n paralelograme, iar operaiile decizionale sunt puse n romburi
i au una sau dou ieiri, pentru cazurile DA respectiv NU n care condiia este adevrat sau fals.
Revenim asupra deniiei uxului de execuie, folosindu-ne de scheme logice de data asta: uxul de
execuie este constituit din sgeile concrete parcurse de PHP la executarea scriptului.

Gsete eroarea de logic**


Partea I

Care sunt greelile algoritmice din pseudocodul urmtor?


1
2
3
4
5
6

daca parola este corecta


afiseaza 'autentificat '
altfel
afiseaza 'parola estegresita '
afiseaza 'aceasta esteo informatie secreta '
afiseaza 'vizibila doar utilizatorilor autentificati '
Identic-le, explic-le n cuvinte, i rescrie pseudocodul corect.

42

Dezvoltare web cu PHP

2.4. ALGORITMI I SCHEME LOGICE

BEGIN

citete
'parola'

aeaz
'Salut '

DA

parola
corect?

NU

aeaz
'necunoscut'

aeaz
'autenticat'

aeaz
'. Ce faci?'

END

Figura 2.1: Flowchart autenticare

Figura 2.2: Cum s urmezi sgeile


Folosete-i intuiia pentru a determina ce ar trebui s fac un astfel de algoritm i ce nu, pe baza
outputului.

Partea II
Deseneaz dou scheme logice10 , una pentru pseudocodul (greit) din partea I a exerciiului, i una
pentru varianta corect a pseudocodului pe care ai gsit-o ca soluie n partea I.
10

Poi folosi programul Dia.

43

Dezvoltare web cu PHP

2.5. TIPUL DE DATE BOOLEAN. EXPRESII LOGICE

Tipul de date boolean. Expresii logice


Seciunea anterioar a tratat parola este corect ca ceva de la sine neles. Poate pentru noi este
uor de neles, ns PHP, i algoritmii n general, nu au noiunea de corect.
Ce nseamn corect de fapt? Cum determinm noi, oamenii, dac o adres, un nume, sau n cazul
de fa o parol, este corect? Ceea ce facem este de fapt compararea a ceva ce vine din exterior, a unui
input, cu ceea ce considerm noi corect, pe baza cunotinelor sau experienelor salvate n creierul
nostru.11
De exact acest lucru are nevoie i PHP. Bine ai venit n lumea expresiilor logice.
Exist nenumrai operatori logici. ns nainte de a trece la ei, trebuie s introducem o funcie
numit var_dump(). n capitolul urmtor vei nva despre funcii pe larg, ns deocamdat o mic
deniie: O funcie este ca o cutie neagr. O hrneti cu parametri, i ea face ceva cu acele valori. n
cazul nostru, vom folosi funcia var_dump() n loc de cuvntul cheie echo pentru a aa att valoarea
pe care i-o pasm ca parametru, ct i tipul su de date. echo nu ar bun pentru asta deoarece ar face
automat nite conversii ntre tipuri de date, i exact acele tipuri de date sunt ceea ce vrem s vedem
neschimbat.
Toate expresiile logice, care conin operatori logici,12 sunt evaluate i au n nal e valoarea adevrat,
e valoarea fals. Deoarece expresiile logice sunt att de importante,13 pentru ele exist i un tip de
date: boolean, sau pe scurt: bool. Acesta este al patrulea tip de date cu care faci cunotin, dup string
(ir de caractere), int (integer numr ntreg) i oat (numr cu virgul).
n contrast cu celelalte tipuri de date, informaii de tipul boolean nu pot avea dect dou valori: TRUE
sau FALSE.
De exemplu, ntr-o aplicaie complex, n care unii utilizatori au drepturi speciale, am putea ntlni:
1

$este_administrator =TRUE;

ns n loc de echo, vom folosi var_dump(), n felul urmtor:


2

var_dump ( $este_administrator );

ncearc, s vezi ce i aeaz. Bineneles c poi aa i valorile constante TRUE sau FALSE direct:
1
2
3

<?php
var_dump (TRUE);
var_dump ( FALSE );

Acum c tim cum se folosete o funcie precum var_dump(), hai s revenim la ideea noastr iniial:
PHP nu tie ce nseamn pentru noi parol corect, deci trebuie s confruntm cele dou valori i s
decidem dac ele sunt una i aceeai.
Aici intr operatorul de comparaie n joc, ==. Acesta este capabil s compare valorile a dou expresii.

Din lucrul nostru cu echo din seciunile anterioare, tii c o expresie poate orice are o valoare,
e ea constant, variabil, rezultatul unei concatenri sau de ce nu, rezultatul unor operaii
matematice.

Ne putem da seama cu uurin cum funcioneaz urmtorul cod:


1
2

<?php
$input ='asdfgh ';// conform unorstudii ,o parola foarte des folosita

3
4
5
6

echo '3==4? ';


var_dump (3==4);
echo'foo=foo? ';

11

Procesele cognitive sunt omise n mod contient, pentru a simplica imaginea.


nu neaprat, dar voi vorbi mai trziu despre asta
13
Exist chiar i o matematic care le susine.
12

44

Dezvoltare web cu PHP

7
8
9
10
11

2.5. TIPUL DE DATE BOOLEAN. EXPRESII LOGICE

var_dump ('foo '=='foo ');


echo'inputul utilizatorului este corect ? ';
var_dump ( $input =='secret ');
echo '3+ -2=0? ';
var_dump (3+ -2==0);

Deoarece nu tim nc cum s cerem input de la utilizator n adevratul sens al cuvntului, simulm
asta folosind variabila $input. Testeaz acelai cod, schimbndu-i valoarea n parola corect, s vezi ce
se ntmpl. n rest, totul ar trebui s e evident: comparaia este evaluat i are e valoarea TRUE, e
valoarea FALSE, care este aat de var_dump().
Urmtorul exemplu ar trebui s ne pun pe gnduri:
1
2

<?php
var_dump ('42'==42);

n interiorul lui PHP, cele dou valori, stringul 42 i int-ul 42, sunt valori complet diferite. ns dup
cum am spus, PHP face tot posibilul pentru a converti o valoare de un tip de date ntr-o alt valoare
de alt tip de date, care s reecte ct mai bine valoarea iniial, nainte de conversie. Din acest motiv,
expresia '42' == 42 este evaluat ca TRUE, stringul 42 ind convertit n int-ul 42 nainte de evaluarea
egalitii celor dou valori constante.
n PHP exist ns i operatorul de comparaie strict, cu vericarea adiional a tipului de date,
folosind operatorul ===.

Veric-i puterea de a face analogii*

Scrie un cod PHP care s aeze valorile a patru comparaii stricte:


1. dintre un int i un string
2. dintre un oat i un int
3. dintre un string i un oat
4. dintre un bool i un string

Am sintetizat corect noiunea de expresie?**


Partea I

Scrie un cod PHP care s aeze valoarea boolean a unei comparaii stricte dintre o expresie
matematic i un string.
Expresia matematic trebuie s conin cel puin o operaie de gradul I, una
de gradul II, i s foloseasc cel puin o dat parantezele rotunde pentru grupare.

Partea II
Explic n cuvinte ce face urmtorul cod:
1
2

<?php
$foo=4== '5';

Dac ai diculti la rezolvarea exerciiului, ar trebui s reciteti nc o dat totul cu atenie,


ncepnd de la pagina 32.

45

Dezvoltare web cu PHP

2.5. TIPUL DE DATE BOOLEAN. EXPRESII LOGICE

Operatorii logici de comparaie i de comparaie strict se mai numesc i operatori relaionali, deoarece
valoarea de adevr rezultat n urma comparaiei stabilete relaia dintre cei doi operanzi.
Operaiile logice de vericare a egalitii i de vericare strict a egalitii pot negate. Acest lucru
se face nlocuind primul = al ecrui operator cu simbolul !. Astfel != se citete este diferit de, iar
!== se citete este strict diferit de.
Pe lng relaia de egalitate, mai exist i operatori logici relaionali care stabilesc inegalitatea.
Acetia sunt ilustrai n tabelul 2.1.
Operator
<
>
<=
>=

Semnicaie
mai mic
mai mare
mai mic sau egal
mai mare sau egal

Tabela 2.1: Operatorii de inegalitate

2.5.1 Conjuncii, disjuncii i negaii


n paginile anterioare ai fcut cunotin cu expresii logice simple. Este ns posibil s unim mai
multe expresii booleene, iar ceea ce rezult este la nal tot o expresie logic boolean, deci va avea una
din valorile TRUE sau FALSE.
Aceste operaii se numesc conjuncii i disjuncii.
O disjuncie reprezint o alternativ. Colocvial recunoatem disjunciile dup cuvntul sau. n
practic, am putea spune Dac plou sau ninge, atunci mi iau ghetele. Nu conteaz care dintre
evenimente va avea loc (sau n termeni booleeni: care dintre evenimente vor adevrate), unul sau
chiar ambele, disjuncia va n orice caz adevrat.
Avnd dou expresii booleene A i B, ecare cu una din valorile de adevr T (TRUE) sau F (FALSE),
n formalism matematic am face calcule de genul:
A=T
B=F

AB =T F =T

O conjuncie n schimb este adevrat doar dac ambele expresii logice A i B sunt adevrate. n
limbajul de zi cu zi recunoatem conjunciile dup cuvntul i.
Formalismul matematic pentru aceeai situaie ca mai sus ar arta astfel:
A=T
B=F

AB =T F =F

Simbolurile matematice pentru disjuncii i conjuncii sunt respectiv , i se citesc sau respectiv
i. n PHP, aceste operaii sunt fcute de operatorii ||, respectiv &&.
Toate combinaiile de TRUE i FALSE sunt reprezentate ntr-un tabel de adevr (en. truth table)14 ,
de exemplu tabelul 2.2.
Dup cum observi, conjunciile i disjunciile sunt comutative ceea ce nseamn c ordinea lor nu
conteaz, rezultatul va acelai. Acest lucru este adevrat, matematic vorbind, ns exist unele cazuri
n care, n programare, exist totui diferene. Ne vom uita la aceste diferene peste cteva seciuni.
Pe lng conjuncii i disjuncii, mai putem i nega o expresie logic. Pentru asta folosim operatorul
! (n PHP), citit not. Simbolul matematic este . TRUE este deci FALSE, iar FALSE este TRUE,
sau n cuvinte: negarea unei armaii este o negaie, respectiv negarea unei negaii este o armaie.
14

http://en.wikipedia.org/wiki/Truth_table

46

Dezvoltare web cu PHP

2.6. CONDIII IF I SWITCH


A
T
T
F
F

B
T
F
T
F

AB
T
F
F
F

AB
T
T
T
F

Tabela 2.2: Tabel de adevr


Deoarece n urma unei operaii logice ne alegem tot cu o valoare boolean, putem nlnui dou sau
mai multe operaii logice, unindu-le printr-o operaie logic. Bineneles c putem i grupa operaii logice
cu paranteze rotunde, la fel ca operaiile matematice.
De exemplu, (T F ) T va mereu TRUE, deoarece, oricare ar rezultatul negaiei expresiei din
parantez, avem apoi o disjuncie, iar <orice> SAU TRUE este mereu TRUE.

Legile lui De Morgan**

Cei inteligeni dintre noi au realizat deja c negarea unei conjuncii este echivalent cu disjuncia
negaiei ecruia dintre cei doi operanzi, i vice-versa: negarea unei disjuncii este echivalent cu
conjuncia negaiei ecruia dintre cei doi operanzi.
F un tabel de adevr similar cu tabelul 2.2, n care calculezi valorile echivalentelor expresiilor (AB)
respectiv (A B), echivalente pe care le gseti aplicnd legile lui De Morgan enunate mai sus.

Operaii logice*

Calculeaz valorile de adevr a urmtoarelor expresii:


1. T F
2. (T F ) T
3. T A(T B) pentru toate valorile posibile ale lui A i B. Creaz tabelul adevrului cu 5 coloane:
A, B, T A, (T B), i T A (T B)
Pn acum ne-am pus la punct cunotinele teoretice despre algoritmic i logic. n seciunile
urmtoare ne vom uita la utilizarea lor practic n PHP.

Asigur-te c ai neles i c stpneti toat teoria i terminologia prezentate pn acum.


Leciile urmtoare nu vor mai relua nici una dintre noiuni, ci vor trece foarte rapid n revist
sintaxa i semantica lucrurilor deja nvate.

Condiii if i switch
n PHP, poi instruciona parserul s execute nite instruciuni doar dac o condiie este adevrat
folosind constructul if. Dup if urmeaz, n paranteze rotunde, o expresie logic. Aceasta poate orice
fel de expresie boolean, de la simpl la complex, cu disjuncii, cojuncii, negaii sau paranteze, exact
aa cum ai vzut n lecia trecut. Dup expresia logic urmeaz un bloc de instruciuni constituit din
una sau mai multe instruciuni ntre acolade.
Cteva exemple:
47

Dezvoltare web cu PHP

1
2
3
4
5
6
7

2.6. CONDIII IF I SWITCH

<?php
$este_administrator =TRUE;
echo'Salut ';
if(TRUE=== $este_administrator ){
echo' Administratorule ';
}
echo '.Euvoifi vazut de toata lumea ';

ncearc acest cod. Apoi schimb valoarea cu care este iniializat variabila $este_administrator n
FALSE. Ce observi?
Listing 2.3: Utilitatea vericrilor
1
2
3
4
5
6
7
8
9
10

<?php
$este_administrator =TRUE;
echo'Salut ';
if(TRUE=== $este_administrator ){
echo'Administratorule ';
}
else{
echo'Utilizatorule ';
}
echo '.Euvoifi vazut de toata lumea ';

n funcie de valoarea de adevr a condiiei (care este o expresie logic), se execut e ramura
if, e ramura else. Dup aceea este continuat execuia liniar. Iar ramura else este complet
opional.

Felul n care poate folosit constructul if este acelai cu felul n care ai folosit constructul dac
n pseudocod i romburile pentru decizii n scheme logice. Liniile 2, 3 i 10 fac parte din execuia liniar,
linia 4 din ambele exemple creaz bifurcaia DA n uxul de execuie, iar linia 7 creaz bifurcaia NU
n al doilea exemplu.

Fi atent la cum am aliniat instruciunile, constructele i acoladele. Se numete formatarea


codului, i este bine s i scrii codul formatat astfel nct doar din alinierea constructelor, ochiul
s poat scana i decide ct mai uor crei ramuri sau bloc aparine ecare instruciune, fr
a nevoit s citeti cu atenie ecare LOC.

Aceste constructe decizionale pot puse unele n altele (en. nested), formnd algoritmi i mai
compleci. De exemplu, s ne imaginm cum ar arta codul unei aplicaii n care vizitatorii pot
autenticai sau nu, iar unii din utilizatorii autenticai au drepturi speciale:
Listing 2.4: Autenticare
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<?php
$este_autentificat =TRUE;
$este_administrator =TRUE;
if( $este_autentificat ){
echo'Esti autentificat .';
if( $este_administrator ){
echo'Esti administrator .';
}
else{
echo'Nuesti administrator .';
}
}
else{
echo'Nuesti autentificat ';
}

48

Dezvoltare web cu PHP

2.6. CONDIII IF I SWITCH

ntrebare de inteligen*

De ce codul anterior nu are n ramura else de pe linia 13 nc un if/else n interior pentru cazul n
care vizitatorul este i administrator?

Schem logic pornind de la cod PHP*

Deseneaz schemele logice ale listingurilor 2.3 i 2.4.


n exemplele anterioare, o variabil putea satisface o condiie, sau nu. Pentru aceste dou cazuri am
pus instruciunile necesare e n blocul if, e n blocul else. Exist ns cazuri n care o variabil poate
lua o valoare dintr-o colecie de dou sau mai multe valori, i vrem ca n ecare caz s e executate anumite
instruciuni. S zicem c aplicaia noastr va avea utilizatori autenticai, moderatori i administratori.
Vom vrea ca toate vericrile s nu e nested, ci liniare:
1
2
3
4
5
6
7
8
9
10
11

<?php
$rol='administrator ';
if(' autentificat '===$rol){
echo'esti autentificat ';
}
elseif('moderator '===$rol){
echo'estimoderator ';
}
elseif(' administrator '===$rol){
echo'esti administrator ';
}

ncearc acest cod de mai multe ori, modicnd de ecare dat valorile variabilelor, s vezi pe unde trece
uxul de execuie.
PHP pune la dispoziie nc un construct pentru astfel de cazuri: elseif. El este contracia unei
combinaii else if, ca n exemplul de mai sus.

elseif

Rescrie exemplul anterior folosind elseif n loc de else if.


Totui, atunci cnd numrul de posibile valori crete (s zicem, $rol poate avea una din 20 de valori),
iar aplicaia trebuie s le trateze pe ecare individual, chiar i codul cu elseif devine greu de citit.
Pentru astfel de cazuri PHP ne pune la dispoziie constructul switch. Sintaxa general arat astfel:
1
2
3

switch ( $variabila ){
// aici tratam diferite cazuri
}

Pentru ecare valoare posibil, n interiorul lui switch punem constructul case urmat de valoarea cu
care confruntm variabila, si apoi :. Vom rescrie exemplul anterior:
1
2
3
4
5
6
7

<?php
$rol='administrator ';
switch ($rol){
case'autentificat ':
echo'esti autentificat .';
case'moderator ':
echo'esti moderator .';

49

Dezvoltare web cu PHP

8
9
10

2.6. CONDIII IF I SWITCH

case'administrator ':
echo'esti administrator .';
}

Schimb pe rnd valoarea variabilei $rol. Vei observa c uxul de execuie va potrivi o valoare (liniile
4, 6 sau 8), ns uxul de execuie nu se va opri la blocul case la care a nceput, ci se va prelinge mai
departe. Pentru a opri, mpiedica uxul de execuie s se extind ctre celelalte blocuri case, trebuie
s adaugi instruciunea break. De exemplu:
1
2
3
4
5
6
7
8
9
10
11
12

<?php
$rol='administrator ';
switch ($rol){
case'autentificat ':
echo'esti autentificat .';
break ;
case'moderator ':
echo'esti moderator .';
case'administrator ':
echo'esti administrator .';
}
echo'suntin afara switch -ului ';

n acest caz, uxul de execuie va trece prin linia 10, doar dac condiiile de pe liniile 7 sau 9 sunt
ndeplinite. Constructul break de pe linia 6 va rupe uxul normal de execuie, forndu-l s revin la
stadiul liniar de dinainte de switch, deci continund execuia (liniar) cu linia 12.
n cazul n care vrem s tratm orice alt valoare netratat de niciun bloc case, putem folosi
ramicaia default, astfel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<?php
$rol='administrator ';
switch ($rol){
case'autentificat ':
echo'esti autentificat .';
break ;
case'moderator ':
echo'esti moderator .';
break ;
case'administrator ':
echo'esti administrator .';
break ;
default :
echo'rolul tauesteinvalid ';
}
echo'suntin afara switch -ului ';

Ramura default nu mai are nevoie de break deoarece este ultima ramur din blocul switch.
Ultima ramur din switch, e ea case sau default, nu are nevoie de break, deoarece nu mai
exist nicio alt ramur dup, deci uxul de execuie nu risc s intre pe o ramur nedorit.

n unele cazuri, vom vrea s-i atribuim unei variabile o valoare pe baza unei condiii. Pentru astfel de
cazuri exist nc un operator, numit operatorul ternar. Se numete astfel deoarece este singurul operator
cu trei operanzi.
Sintaxa general este:
<condiie> ? <dac-TRUE> : <dac-FALSE>;
Acest ntreg conglomerat va nlocuit de una din expresiile <dac-TRUE> sau <dac-FALSE>, n
funcie de valoarea de adevr a condiiei.

50

Dezvoltare web cu PHP

2.7. BUCLELE WHILE I DO WHILE

Asta nseamn c ntregul construct poate pus oriunde PHP accept o expresie. Deoarece
<dac-TRUE> i <dac-FALSE> sunt ele nsei expresii, putem avea deci operaii ternare una
n alta (en. nested).

Ceea ce am scris anterior astfel:


1
2
3
4
5
6
7
8
9

<?php
$rol='administrator ';
if(' administrator ===$rol){
$este_administrator =TRUE;
}
else{
$este_administrator = FALSE ;
}
var_dump ( $este_administrator );

putem scrie mult mai compact astfel:


1
2
3
4

<?php
$rol='administrator ';
$este_administrator ='administrator '===$rol?TRUE: FALSE ;
var_dump ( $este_administrator );

nelegerea operatorului ternar**


Partea I

Explic n cuvinte ce face linia 3 din exemplul anterior.

Partea II
Explic n cuvinte ce se ntmpl concret n acest cod:
1
2
3
4
5

<?php
$rol='administrator ';
if('test '===($rol==='administrator '?'test ':'test2 ')){
echo'administrator ';
}

Pentru dou cazuri, cnd $rol are valoarea administrator, i cnd are o alt valoare.

Buclele while i do while


Buclele constituie modalitatea de a executa un bloc de instruciuni n mod repetitiv, atta timp ct
o condiie este adevrat.
Sintactic, cele dou bucle, while i do while arat astfel:
1
2
3
4
5
6

while (<conditie >){


<bloc -de - instructiuni >
}
do{
<bloc -de - instructiuni >
} while (<conditie >);

Schema logic a buclei while arat ca n gura 2.3.


Dac condiia este din start fals, atunci se continu execuia liniar (n jos), altfel se trece prin
blocul de instruciuni (care bineneles c poate conine mai multe instruciuni, sau chiar alte bucle,

51

Dezvoltare web cu PHP

2.7. BUCLELE WHILE I DO WHILE

DA

condiie?

bloc de
instruciuni

NU

Figura 2.3: Flowchart bucl while


constructe if/else, switch, .a.m.d.). Dup ce instruciunile au fost executate, se ajunge iar la vericarea
condiiei, i povestea o poate lua de la capt.

Blocul de instruciuni trebuie s modice cumva valoarea de adevr a condiiei care urmeaz
a vericate. Altfel riscm s crem o bucl innit, din care uxul de execuie nu va iei
niciodat.
La acest lucru se ajunge de obicei folosind cel puin o variabil n condiie, a crei valoare se
schimb n blocul de instruciuni.

De exemplu, putem numra de la unu la zece, din unu n unu. Pentru asta, valoarea de start este
evident 1. Aceast valoare o vom salva ntr-o variabil. La ecare rulare a buclei, adunm 1 la valoarea
variabilei, i salvm rezultatul n aceeai variabil. Astfel avansm de la 1 la 2, de la 2 la 3, .a.m.d.,
pn la 10. Condiia de oprire va ca valoarea variabilei s e mai mic sau egal cu 10. Dac condiia
nu este adevrat, atunci uxul de execuie trece peste blocul while, i se continu execuia liniar.
Schema logic ar arta ca n gura 2.4.

Numrtoarea din 1 n 1 cu while*


Partea I

Implementeaz algoritmul din gura 2.4 n limbajul PHP.

Partea II
ntrebare capcan: Ce valori va lua pe rnd variabila $var?
Do while este foarte asemntoare cu bucla while, diferena ind c blocul de instruciuni va
executat cel puin o dat. Ceea ce este logic, din moment ce mai nti se trece prin blocul de instruciuni,
apoi este vericat condiia, i dac aceasta este TRUE, atunci se sare napoi, la nceputul blocului de
instruciuni.
n alt ordine de idei, iniial blocul de instruciuni face parte din execuia liniar. Abia apoi se va
decide, n funcie de valoarea de adevr a condiiei, dac se va crea o bucl sau nu. Din asta deducem
c uxul de execuie poate trece prin bucla do while fr a face nicio bucl de fapt, fr a sri napoi
nici mcar o dat. Asta s-ar putea ntmpla dac condiia ar din start fals. ns n contrast cu bucla
while, blocul de instruciuni al buclei do while va executat cel puin o dat.
52

Dezvoltare web cu PHP

2.7. BUCLELE WHILE I DO WHILE

BEGIN

$var = 1

TRUE
$var <= 10

aeaz
$var

FALSE

$var = $var + 1

END

Figura 2.4: Numrnd de la 1 la 10

Schema logic a buclei do while*

Modic schema logic general a buclei while din gura 2.3, transformnd-o n schema logic a
buclei do while.

Numrtoarea din doi n doi cu do while*


Partea I

Scrie un program care s numere descresctor din 2 n 2, ncepnd de la 23 i terminnd cu un numr


negativ la alegere, folosind bucla do while.

Partea II
Ce face programul tu i nu este n cerin?

Par sau impar?**

Alege un numr pozitiv nenul N i scrie un program care pentru toate numerele din intervalul [-N;N]
aeaz dac acestea sunt pare sau impare. Pentru N=42, outputul va arta astfel:
-42 este par
-41 este impar
53

Dezvoltare web cu PHP

2.7. BUCLELE WHILE I DO WHILE

-40 este par


...
0 este par
...
41 este impar
42 este par
Valorile constante este, par i impar trebuie s apar o singur dat n cod, iar codul trebuie s fac
uz de operatorul ternar i de operatorul modulo.

2.7.1 break i continue


Constructul break l-am ntlnit deja n folosirea constructului switch. ns break, dup cum i
sugereaz i numele, poate mai mult: poate ntrerupe orice bucl.15 Fluxul de execuie din bucl pur i
simplu va sri din interiorul buclei n afara ei, continund uxul liniar de dup bucl.
Unul din scenariile n care avem nevoie de el ar putea cutarea: cutm un element ntr-o bucl,
i atunci cnd l-am gsit, ntrerupem cutarea nu ar mai avea rost s terminm de iterat tot setul de
date.
De exemplu, dndu-se un numr ntreg N ca input, vrem s am urmtorul multiplu de 10. Am
putea face asta n felul urmtor:
1
2

<?php
$n=231;

3
4
5
6
7
8
9

while (TRUE===TRUE){
if (0===$n %10){
break ;
}
$n+=1;
}

10
11

echo'N rotunjit prin adaugire este',$n;

Linia 4 ne-ar putea prea ciudat, i ntr-adevr este. Ea transform automat bucla while ntr-una
innit, deoarece, n mod evident, valoarea de adevr a comparaiei nu se va schimba niciodat. ns
acest lucru este voit, deoarece practic ntrerupem bucla uxului de execuie folosind break.

R
U

Dac nu nelegi linia 5, atunci cel mai probabil nu ai sintetizat destul la ce este util restul
operaiei de mprire, i deci operatorul modulo, prezentat la pagina 40.

Revizuiete lecia Teorema mpririi cu rest, nvat la matematic n clasa a V-a.

Majoritatea buclelor innite pot corectate

Rescrie codul anterior mutnd (i eventual modicnd) condiia de ntrerupere a buclei (deci condiia
din if), i renunnd complet la folosirea break.
Ce crezi, codul este acum mai curat sau nu?
Constructul continue ne permite s srim peste restul instruciunilor urmtoare din ciclul curent al
buclei, trecnd la ciclul urmtor.
15

A nu se nelege c switch ar o bucl nu este

54

Dezvoltare web cu PHP

2.8. TIPUL DE DATE ARRAY. BUCLA FOREACH

De exemplu, putem aa doar numerele care sunt multiple de trei, i calcula suma celorlalte numere
din intervalul de numere [0,50] astfel:
1
2
3
4
5
6
7
8
9
10
11
12
13

<?php
$n=0;
$sum=0;
while ($n <=50){
if (0===$n %3){
echo$n ,' ';
$n+=1;
continue ;
}
$sum+=$n;
$n+=1;
}
echo'Sumaeste',$sum;

Datorit liniei 8, uxul de execuie va sri napoi pe linia 4. Deoarece la urmtoarea iteraie a buclei nu
vrem s intrm cu aceeai valoare pentru $n, cci ne-am alege cu o bucl innit, adugm 1 la valoarea
lui $n, i salvm rezultatul tot n $n pe linia 7, nainte de a face saltul napoi la vericarea condiiei.

Tipul de date array. Bucla foreach


Pn acum am lucrat doar cu tipuri de date scalare: string, int, oat, bool. Un array este un tip de
date compozit i poate folosit n cele mai diverse situaii, motiv pentru care este foarte versatil.
Pentru a iniializa un array, atribuim valoarea array() unei variabile. Aceasta va conine un array
gol. Exemplu:
1
2
3
4

<?php
$a= array ();
var_dump ($a);
var_dump ( array ());

Din asta deducem c array() poate la fel de bine o expresie, deci poate folosit aa cum am folosit
orice alt valoare de pn acum, precum TRUE, 42, sau foo:
1
2
3
4
5
6

<?php
$a= array ();
var_dump ($a=== array ());
if($a=== array ()){
echo'$aesteun array gol ';
}

n loc de a compara o variabil cu array(), PHP ne pune la dispoziie un construct special: empty().
Acesta, mpreun cu variabila din interiorul parantezelor rotunde, este nlocuit de o valoare boolean.
Testeaz urmtorul exemplu:
1
2
3

<?php
$a= array ();
var_dump ( empty ($a));

Concluzionm c empty() poate folosit oriunde am folosit pn acum expresii logice, de exemplu n if:
1
2
3
4
5
6
7
8

<?php
$a= array ();
if(TRUE=== empty ($a)){
echo'$aestegol ';
}
else{
echo'$aesteplin ';
}

55

Dezvoltare web cu PHP

2.8. TIPUL DE DATE ARRAY. BUCLA FOREACH

Pentru a iniializa un array cu elemente n el, le putem pune ntre parantezele rotunde ale lui array(),
separndu-le unul de altul prin virgul:
1
2
3
4
5
6
7
8

<?php
$a= array (42,'foo ',TRUE , FALSE );
if(TRUE=== empty ($a)){
echo'$aestegol ';
}
else{
echo'$aesteplin ';
}

Sper c acum este evident de ce un array este un tip de date compozit: n el poi salva alte valori de
diferite tipuri de date.
Exact, un array salveaz n el valori precum cele constante de mai sus. Putem chiar i copia valorile
altor variabile n array:
1
2
3

<?php
$foo='bar ';
$a= array (42, $foo);

Este incorect s spui c variabila $foo este n array-ul $a. Nu variabila este ntr-un array, ci
valoarea acesteia. A doua linie se citete deci astfel: Copiaz valoarea constant 42 i valoarea
variabilei $foo ntr-un array, i atribuie array-ul rezultat variabilei $a.

Dup ce avem un array, vom vrea s prelucrm valorile salvate n el ntr-o bucl, ecare element pe
rnd.
Deoarece array-urile sunt foarte importante, PHP ne pune la dispoziie nc o bucl, special gndit
pentru ceea ce numim iterarea array-urilor. Bucla se numete foreach.
Sintaxa general arat astfel:
foreach(<array> 'as' <value>) {
<bloc-de-instructiuni>
}
<array> este array-ul pe care vrem s-l iterm, <value> este o variabil inventat de noi care exist
doar n interiorul buclei i care va lua pe rnd valorile pstrate n array, la ecare iteraie a buclei.
S zicem c avem o list de nume, i vrem s le am pe toate unul sub altul, n HTML:
1
2

<?php
$names = array ('Mircea ','Claudiu ','Ioana ','Flavius ');

3
4
5
6
7

foreach ( $names as $name ){


echo'Salut ',$name ,'!<br >';
}
echo'Hooray !';

Meniu de navigare*
Partea I

Scrie un cod care pornind de la un array precum


1

$menu = array ('Home ','Contact ','Despre ');

genereaz un meniu de navigare (tag-urile <ul> i <li>). Structura codului HTML va trebui s arate
astfel:
56

Dezvoltare web cu PHP

2.8. TIPUL DE DATE ARRAY. BUCLA FOREACH

<ul>
<li><a href="#Home">Home</a></li>
<li><a href="#Contact">Contact</a></li>
<li><a href="#Despre">Despre</a></li>
</ul>

Partea II
mbuntete codul astfel nct dac $menu este iniializat gol, astfel:
1

$menu = array ();

s nu mai genereze un meniu, ci output-ul:


Meniu inexistent.
Pentru asta va trebui s verici dac array-ul este gol cu empty($menu), dac nu, s faci ceea ce ai fcut
n partea I a exerciiului, altfel s generezi outputul Meniu inexistent.
Exerciiul Meniu de navigare i-a introdus subtil avantajele array-urilor. Este adevrat c la nceput
codul va mult mai complex dect un meniu static n HTML, ns dup ce ai codul, i acesta funcioneaz,
nu trebuie dect s modici valorile salvate n array, ntr-un loc central, i PHP va genera mereu meniul
HTML corespunztor. Nu vei mai avea de-a face cu HTML direct, nu mai mult dect ai descrie un singur
element <li>, un singur element <ul> sau un singur element <a>. Asta este posibil mulumit proprietii
unei bucle de a repeta un bloc de instruciuni.
Ceea ce am fcut n exerciiul anterior se numete inventarea unei structuri de date abstracte (n cazul
nostru este un array, pe care l-am salvat n $menu) care emuleaz ceea ce cunoatem ca ind un meniu
n viaa real. Dei nu este el nsui un meniu, conine toate datele de care avem nevoie pentru a genera
dinamic un meniu, cu PHP. Aceste date se numesc metadate, concept pe care l-ai cunoscut la nceputul
acestui capitol.

R
U

Dup cum i-am spus nc de la nceputul capitolului, i dup cum tocmai ai vzut, toate
aplicaiile conin metadate. Ele vin deseori mpachetate n structuri de date abstracte precum
array-ul salvat n $menu.

Obinuiete-te cu ideea de a trebui s inventezi date abstracte care conin metadate. Este
adevrat, la nceput va trebui s investeti mai mult timp n conceperea acestor date abstracte,
dar pe termen lung avantajele n termeni de mentenabilitate, exibilitate i reutilizare a codului
se vor face simite.

Dup ce un array a fost iniializat, putem aduga elemente adiionale la sfritul su, folosind
operatorul []. Sintaxa general este:
$<array>'[]' = <valoare>
Exemplu:
Listing 2.5: Adugarea elementelor la sfritul unui array
1
2
3

<?php
$names = array ('Mircea ','Claudiu ','Ioana ','Flavius ');
$names []='Ramona ';

Convinge-te, scrie un cod care itereaz array-ul rezultat dup adugarea elementului Ramona.
Pn acum, la ecare iteraie a array-ului, valoarea curent era pus n variabila de dup as. ns
elementele dintr-un array au i un index, o ordine. Pentru a ajunge la acest index, foreach are o sintax
extins:
57

Dezvoltare web cu PHP

2.8. TIPUL DE DATE ARRAY. BUCLA FOREACH

foreach(<array> 'as' <index> '=>' <valoare>) {


<bloc-de-instructiuni>
}

Sintaxa foreach**

Scrie un program care itereaz toate elementele dintr-un array i aeaz pentru ecare Elementul
<I> are valoarea <V>, unde <I> este indexul, <V> este valoarea.

Acest exerciiu i testeaz capacitatea de a nelege o specicaie sintactic i de a o aplica n


practic, scriind un cod PHP care o respect.

Dup cum ai observat, elementele dintr-un array sunt numerotate de la zero la N-1, unde N este
numrul total de elemente. Din acest motiv, spunem c un array este 0-indexed. Astfel de array-uri se
mai numesc i vectori sau liste.
Pot exista situaii n care vrem un anumit element din array, tiindu-i indexul. n astfel de cazuri
folosim sintaxa urmtoare pentru a accesa acel element:
$<array>'['<index>']'
<index> poate orice expresie care are o valore, aa cum am vzut pn acum, deci asta include i
operaii matematice:
1
2

<?php
$names = array ('Mircea ','Claudiu ','Ioana ','Flavius ');

3
4

$index_fata =2;

5
6
7
8

echo'Eusunt',$names [3],'<br >';


echo'Pefatao cheama ',$names [ $index_fata ],', inaintea eieste',
$names [ $index_fata -1],'iardupaea urmeaza ',$names [ $index_fata +1];

S zicem c avem urmtoarea situaie: avem un array de nume, i numele nostru i vrem s am
numele imediat dup numele nostru.
Am putea proceda n felul urmtor:
Listing 2.6: Indexurile sunt consecutive
1
2
3
4

<?php
$names = array ('Mircea ','Claudiu ','Ioana ','Flavius ');
$me='Claudiu ';
$after_me ='<nimeni >';

5
6
7
8
9
10
11

foreach ( $names as $index => $name ){


if($name ===$me){
$after_me = $names [ $index +1];
break ;
}
}

12
13

echo'Dupamineeste',$after_me ;

ncearc acest cod. Apoi ncearc s vezi ce se ntmpl dac variabila $me este iniializat cu ultima
valoare din array. Exact, va spune c indexul $index+1 nu exist, ceea ce e normal.
Pentru a verica dac ceva e setat, PHP ne pune la dispoziie nc un construct, similar cu empty():
isset(). Acesta este nlocuit cu o valoare boolean care reect existena parametrului pe care i-l pasm.
n cazul nostru, am folosi isset($names[$index+1]).

58

Dezvoltare web cu PHP

2.8. TIPUL DE DATE ARRAY. BUCLA FOREACH

O conjuncie n practic

Adaug conjunctiv condiia isset($names[$index+1]) la condiia deja existent de pe linia 7 din


codul anterior.
ns putem asocia ecrui element dintr-un array i un index explicit. Pentru asta folosim aceeai
sintax ca n partea de dup as din bucla foreach: <index> '=>' <value>.
Iniializarea unui astfel de array ar arta astfel:
1
2
3
4
5

$fructe = array (
231 =>'mere ',
1=>'pere ',
1001 =>'alune '
);

Un array cu date asociative se mai numete i dicionar. El asociaz indecii (sau cheile) din stnga, cu
valorile din dreapta.

Nu este obligatoriu s formatezi astfel codul, ai putut scrie totul pe o singur linie. ns e o
practic bun s l scrii aa, pentru a ct mai lizibil.

Dac indexul lipsete, atunci se ia indexul cel mai mare existent n array pn n acel moment, i se
incrementeaz cu o unitate. De exemplu, n codul:
1
2
3
4
5
6
7

$fructe = array (
231 =>'mere ',
1=>'pere ',
1001 =>'alune ',
'piersici ',
'caise '
);

elementul cu valoarea piersici va asociat automat cu indexul 1002, iar caise va salvat la indexul
1003, deoarece 1002 exist deja.
De fapt, un astfel de dicionar nu este limitat doar la indeci numerici. Poi folosi i stringuri pentru
asocieri. De exemplu, familia mea ar putea abstractizat ntr-un array astfel:
1
2
3
4
5
6

$my_family = array (
'me '=>'Flavius ',
'father '=>'Adrian ',
'mother '=>'Simona ',
'brother '=>'Daniel '
);

Folosind ns un array asociativ n loc de un array indexat16 , pierdem automat din consistena
ordonrii datelor. O problem de genul celei ilustrate n codul 2.6 nu ar mai aa uor rezolvabil,
deoarece $index+1 nu ar mai exista.
Aadar, cnd trebuie s concepem o structur de date, trebuie s ne gndim bine dac este o asociere,
sau o niruire. Dac este o asociere, atunci vom vrea s folosim chei expresive crora s le asociem
informaii. Dac n schimb constatm c vrem o niruire, atunci nu ar trebui s ne bgm nasul peste
numerotarea indecilor, i s l lsm pe PHP s fac asta pentru noi, n mod consistent, automat.
Dei cele dou moduri n care pot folosite array-urile pot amestecate, n aceast carte vom folosi
termenul de index atunci cnd ne referim la array-uri ca la liste de elemente numerotate automat, iar
termenul de cheie (en. key) atunci cnd intenionm s folosim informaiile n mod asociativ.
Indiferent de cum folosim array-ul, indexat sau asociativ, putem citi din el i scrie n el date folosind
operatorul [], aa cum am mai vzut:
16

Se subnelege c elementele sunt numerotate consecutiv de la 0 la N-1.

59

Dezvoltare web cu PHP

1
2
3
4
5
6
7
8

2.9. BUCLA FOR

<?php
$posesor ='Flavius ';
$fructe = array ('mere ');
$fructe []='pere ';
$fructe [23]='alune ';
$fructe ['favorit ']='capsuni ';
$fructe [' favoritul lui '. $posesor ]='piersici ';
$fructe [23*4 -1]='caise ';

9
10
11
12

echo'<pre >';
var_dump ( $fructe );
echo '</pre >';

13
14

echo'Celemaitarisunt',$fructe [' favoritul luiFlavius '],'le ';

Exact, chiar i n interiorul lui [] putem folosi orice expresie, expresie a crei valoare este evaluat mai
nti, pentru care PHP creaz o valoare temporar, i care e folosit ca cheie apoi.

Bucla for
n unele din exemplele anterioare am iniializat mai nti variabile precum $sum cu valoarea 0 nainte
de intrarea ntr-o bucl, iar la ecare iteraie am vericat apoi valoarea de adevr a unei expresii booleene
(condiia buclei) i eventual am adugat unu la un numr.
Bucla for ne permite s facem astfel de lucruri mult mai elegant. Sintaxa general este
for(<initialization> ; <condition> ; <expr>) {
<block-of-instructions>
}
<initialization> este executat o singur dat, nainte ca uxul de execuie s intre n bucla efectiv,
<condition> i <expr> sunt executate la ecare iteraie a buclei.
Pentru a numra de la 0 la 100 am putea scrie:
1
2
3
4

<?php
for($i =0;$i <=100; $i+=1){
echo$i ,' ';
}

Iniializarea i expresia pot conine iniializri respectiv expresii multiple, separate prin virgul.

Dou cte dou**


Partea I

Scrie un program folosind bucla for cu iniializri i expresii multiple care calculeaz suma ecrui
numr par de la 0 la 50 cu numrul impar care l succed. Altfel spus, 0+1, 2+3, 4+5, . Output-ul
trebuie s arate aa:
0 + 1 = 1<br>
2 + 3 = 5<br>
...
50 + 51 = 101<br>

Partea II
Rescrie programul folosind o singur variabil.

60

Dezvoltare web cu PHP

2.10. COMPLETRI

Completri
Ultimele lecii i-au prezentat foarte multe lucruri noi, ns am srit intenionat peste multe noiuni
tocmai pentru c voiam s ai ct de ct o imagine de ansamblu mai nti. Aceast seciune i va slefui
cteva noiuni deja cunoscute, aducnd i completri, i mai ales sfaturi despre cum s-i scrii codul
curat, elegant.

2.10.1

Stringuri

Pn acum stringurile au fost scrise mereu ntre apostrofuri. Acestea se numesc stringuri simple.
n PHP exist ns i stringuri interpretate, sau mai bine zis stringuri interpolate. Se numesc aa
deoarece numele variabilelor din interiorul lor sunt interpretate i nlocuite de valorile lor.
Astfel, n loc de:
1
2
3

<?php
$nume ='Flavius ';
echo'Salut ',$nume ;

Poi scrie:
1
2
3

<?php
$nume ='Flavius ';
echo" Salut $nume ";

Pe lng variabile, n stringurile interpolate mai sunt interpretate i aa-zisele caractere de control.
Aceste caractere sunt mai mult sau mai puin invizibile. Aceste caractere ncep cu \(en. backslash), i
sunt urmate de ceva, de obicei de un caracter.
De exemplu, pn acum ai generat cod HTML, cel mai probabil apelnd de mai multe ori echo. ns
dac te-ai uitat la codul surs HTML generat, tot acest cod era ntr-o linie. Pentru asta am putea pune
o linie nou folosind un astfel de caracter numit line feed. ncearc:
1
2
3

<?php
echo" Salut \n";
echo" Flavius ";

Dup cum tii, HTML nu interpreteaz liniile noi ntr-un mod special. ns dac te uii la sursa generat,
sau faci o cerere cu telnet, vei vedea c cele dou stringuri se a pe linii diferite, unul sub altul. De
fapt, nici nu e nevoie s foloseti dou stringuri constante, poi scrie totul ntr-un crnat lung:
1
2

<?php
echo" Salut \ nFlavius ";

Dei nu este un spaiu ntre cuvinte, browserul interpreteaz corect linia nou i aeaz un spaiu ntre
ele, deoarece aa dicteaz formatul HTML.
Un alt caracter special este \t. Acesta are acelai efect cu apsarea tastei TAB .
Deoarece caracterul \ este folosit pentru ceea ce numim escaping, pentru a aa caracterul backslash
nsui trebuie s l escape-uim i pe el, deci ne alegem cu dou caractere backslash pentru a reprezenta
un singur caracter. Exemplu:
1
2
3

<?php
echo '\se numeste backslash ';
echo"\\se numeste backslash ";

Caracterul \ este folosit din motive istorice, ar putut orice alt caracter.
n exerciiul Sintaxa HTML de la nceputul capitolului, ai pus de exemplu caractere precum <
ntre apostrofuri, tocmai pentru a diferena caracterul < care are o semnicaie special n metalimbajul
inventat de noi de caracterul < care voiai s e interpretat exact aa cum e. Altfel spus, punnd
61

Dezvoltare web cu PHP

2.10. COMPLETRI

caractere ntre apostrofuri, am spus c acest caracter trebuie scpat printre degete, deci nu trebuie
interpretat de metalimbaj, si face parte din input/output.
Pentru a nelege ce nseamn acest scpat printre degete, trebuie s nelegem cum funcioneaz
parsarea n PHP.17
Atunci cnd PHP execut un script, primul lucru pe care l face este s citeasc ierul PHP scris
de noi, caracter cu caracter. PHP citete rnd pe rnd caracterele e,c,h,o, i deoarece recunoate
acest ir de patru caractere ca ind constructul echo, tie c ce urmeaz trebuie s e o expresie cu o
valoare. Altfel spus, echo pune parserul n contextul semantic de a se atepta la o expresie.
Apoi PHP ajunge la caracterul , i tie c urmeaz un ir de caractere care trebuie luat ca atare,
ca o valoare constant. PHP tie i c trebuie s citeasc caractere i s le pun n acest string pn
ntlnete iar caracterul .
Hai s vedem ce se ntmpl n cazul urmtor:
1

echo'You 'reonline ';

PHP citete echo, vede spaiul i l accept pe echo ca construct al limbajului, apoi vede i ncepe
s pun, caracter cu caracter, literele Y,o,u ntr-un nou string. Apoi, deoarece a ntlnit nc o dat , i
deoarece tocmai se a deja in contextul semantic al unui string, PHP i d seama c acesta e sfritul
stringului. Altfel spus, PHP ar executa asta:
1

echo'You '

Problema este c la sfritul instruciunii PHP se ateapt s vad ori ,, ori ;, deci se blocheaz la
1

reonline ';

care nu e o instruciune valid nici mcar din punct de vedere sintactic.


n interiorul stringurilor simple, delimitate de apostrofuri, caracterul are semnicaia special de a
termina nsui stringul. Escaping nseamn s-l form pe PHP s scape printre degete aceste caractere
speciale. Pentru a face escaping, vom precede caracterul special cu \:
1
2

<?php
echo'You\'reonline ';

Astfel PHP, atunci cnd ntlnete \, tie c urmtorul caracter nu trebuie interpretat ntr-un mod
special, ci doar adugat la stringul pe care tocmai l citete.
n astfel de cazuri poi ns s foloseti stringuri interpretate, deoarece n interiorul lor caracterul
nu mai are semnicaia de delimitator:
1
2

<?php
echo"You 're online ";

Similar, atunci cnd vrei s construieti un string care conine cod HTML, mult mai curat este:
1

echo'<form method =" post ">';

dect:
1

echo"<form method =\" post \" >";

Vor exista cazuri n care vei nevoit s salvezi stringuri constante foarte largi ntr-o variabil, sau s
aezi o astfel de valoare.
Pentru astfel de cazuri exist dou tipuri de stringuri: nowdoc i heredoc. Cele dinti se manifest
exact ca stringurile simple, cele din urm sunt stringuri interpolate.
Stringurile nowdoc sunt introduse de operatorul '<<<'urmat de un string neinterpretat. Acest string
va folosit de PHP ca marcaj pentru a determina sfritul stringului. Marcajul de sfrit trebuie s
apar pe o singur linie i s e primul i singurul lucru pe acea linie, fr a precedat nici mcar de
spaii, i urmat doar de ;. Exemplu concret:
17

De fapt, lexicalizarea, un pas din parsare. Detaliile mai mult l-ar induce n eroare pe cititor.

62

Dezvoltare web cu PHP

1
2
3

2.10. COMPLETRI

echo <<<'EOD '


$fooesteo variabila
EOD;

Bineneles c poi atribui valoarea unei variabile, sau face orice alte operaii cu un astfel de string:
1
2
3
4

<?php
$bar= <<<'EOD '
$fooesteo variabila
EOD;

Sintaxa heredoc pentru stringurile interpolate este foarte asemntoare:


1
2
3
4
5

<?php
$foo='bar ';
echo <<<EOD
$fooesteo variabila
EOD;

Avantajele heredoc i nowdoc fa de stringurile interpolate sau simple este c caracterele respectiv
pot folosite fr niciun fel de restricie.

2.10.2

Constante i alte tipuri de date

n PHP exist cteva constante predenite pe care PHP le creaz automat pentru noi. Constantele
urmeaz aceleai standarde de denumire ca i variabilele, cu dou excepii:
identicatorul constantei nu este precedat de simbolul $
constantele denite de programator nu trebuie s nceap cu dou caractere underscore, deoarece
acestea sunt rezervate pentru adugiri viitoare n limbaj
Sintaxa denirii unei constante este
const <identificator> = <valoare>;
<valoare> poate orice expresie care evaluat, rezult ntr-o valoare, de orice tip ar aceasta: int, oat,
string, sau bool. Array-urile, ind un tip de date compozit, nu pot salvate n constante.
O constant, aa cum i spune i numele, nu i poate schimba valoarea o dat ce a fost denit.
Constantele sunt evaluate ca expresii, deoarece au valori, ca i variabilele. Exemple:
1
2

<?php
const NUME='Flavius ';

3
4
5

echo'Salut ',NUME;
echo'Cefaci '.NUME .'?';

PHP i pune la dispoziie multe constante predenite, ns doar cteva sunt de interes general pentru
noi deocamdat.
Fiecare sistem de operare are o reprezentare proprie a caracterului linie nou. Windows folosete
\r\n (o serie de dou caractere), Linux are \n iar Macintosh folosete \r. Constanta PHP_EOL
va avea mereu valoarea corect pentru ecare sistem de operare.
Alte constante predenite de interes general sunt PHP_VERSION, PHP_OS, PHP_SAPI,
PHP_INT_MAX valoarea maxim a unui numr ntreg, INF pentru reprezentarea innitului, NAN
(en. not a number) pentru valori care nu sunt numere.
Exist cteva constante magice n PHP. Acestea i schimb valoarea n funcie de context. Pentru
noi interesante sunt deocamdat __LINE__ pentru linia curent, __FILE__ pentru ierul curent,
i __DIR__ pentru directorul n care se a ierul curent. __LINE__ este foarte util pentru a
determina prin ce linii a trecut uxul de execuie, i deci pentru a depana (en. debugging) logica
scriptului. Exemplu:
63

Dezvoltare web cu PHP

1
2
3
4
5
6
7
8
9
10
11

2.10. COMPLETRI

<?php
echo'PHP incepe executia scriptului "',__FILE__ ,'"<br/>';
$test =TRUE;
echo'Fluxul de executie trece prin linia ',__LINE__ ,'<br/>';
if(TRUE=== $test ){
echo'Fluxul de executie trece prin linia ',__LINE__ ,'<br/>';
}
else{
echo'Fluxul de executie trece prin linia ',__LINE__ ,'<br/>';
}
echo'Fluxul de executie trece prin linia ',__LINE__ ,'<br/>';

Exist nc un tip fundamental de date n PHP: NULL. Tipul NULL este pentru iniializarea
variabilelor care pot lua valori diferite, de tipuri diferite, i pentru care nu tim a priori ce tip de date
vor avea.
NULL mai este bun i pentru iniializarea variabilelor care urmeaz s e stringuri, i vrem s ne
asigurm c acea variabil va exista.
NULL este util i pentru a semnaliza c o variabil are o valoare invalid. De exemplu, lucrm la
un magazin online i i cerem utilizatorului s introduc numrul de buci dorite. Iniializm variabila
cu NULL, pentru a ne asigura c aceasta va exista, indiferent de ce va introduce utilizatorul, apoi citim
inputul. Dac utilizatorul nu introduce o cantitate, noi vedem c variabila nc are valoarea NULL, lucru
din care deducem c utilizatorul nu a introdus o cantitate, deci am o eroare. La un minim, un astfel
de algoritm ar arta astfel:
1
2
3
4
5
6
7
8
9
10

$cantitate =NULL;
// nustimincacumsa citim input ,darhaisa presupunem
// ca urmatoarea linie puneinmod magic valoarea introdusa in variabila
// $cantitate = $input ;
if(NULL!== $cantitate ){
echo"Ati comandat $cantitate bucati ";
}
else{
echo'Eroare : trebuie sa introduceti ocantitate ';
}

De fapt, NULL, TRUE i FALSE sunt constante n PHP, numai c sunt ntmpltor susinute n
mod ocial de PHP.
Type casting i convertirea implicit
Type casting nseamn a converti o variabil care are o valoare de un tip de date ntr-o valoare de un
alt tip de date. Pentru asta punem noul tip de date n paranteze, urmat de valoarea pe care vrem s o
convertim. Spunem c am convertit explicit valoarea dintr-un tip de date n altul. Exemplu:
Listing 2.7: Type casting explicit
1
2
3
4
5
6
7
8
9
10
11
12
13
14

<?php
var_dump (5);
var_dump (( string )5);
var_dump ('TRUE ');
var_dump ((bool)'TRUE ');
var_dump ((bool)'');
var_dump (( string ) array ());
var_dump ((bool) array ());
var_dump ((bool) array (''));
$test =( float )'FALSE ';
var_dump ( $test );
var_dump ((bool)5);
var_dump ((bool)0);
var_dump ((bool) -42);

64

Dezvoltare web cu PHP

2.10. COMPLETRI

Observaii type casting*

Explic n limba romn, cu cuvinte proprii, tot ce observi n codul de mai sus.
Ce valori i de ce tipuri de date rezult n ce valori convertite n ce tipuri de date?
Ce valori sunt evaluate ca TRUE, i ce valori ca FALSE?
Unele valori sunt evaluate ca FALSE atunci cnd sunt sunt folosite n contextul unei expresii booleene.
Spunem c o valoare este convertit implicit. Dac pn acum am scris:
1
2
3
4
5

<?php
$test =TRUE;
if(TRUE=== $test ){
echo'esteadevarat ';
}

mult mai scurt ar fost:


1
2
3
4
5

<?php
$test =TRUE;
if($test ){
echo'esteadevarat ';
}

Deoarece valoarea variabilei $test este convertit automat n tipul bool, aa cum ai vzut n listingul 2.7.
Automat sunt convertite i valorile numerice (int i oat) care sunt de fapt stringuri, atunci cnd
aceste stringuri sunt folosite n contextul unor operaii matematice:
1
2
3
4

<?php
$foo= '3.14 ';
$bar= '2';
echo$foo*($bar+3);

Este greit s salvezi valori numerice ca stringuri, s faci operaii matematice cu aceste stringuri
i s te bazezi pe PHP c va face conversiile automat. Valorile pe care le salvezi n variabile
sau n constante trebuie s reecte tipul lor de date.

2.10.3

Ali operatori

Deseori am fost nevoii s adugm sau s scdem 1 la o variabil. Aceste operaii se numesc a
incrementa respectiv a decrementa o variabil.
Iniial am fcut asta explicit, aa:
1

$foo=$foo+1;

Apoi am vzut c putem uni o operaie matematic cu operaia de atribuire, i am folosit:


1

$foo -=1;

Aceste operaii sunt foarte des ntlnite, n special n bucle (predominant n for, dar i n alte bucle), deci
avem doi operatori speciali pentru asta: ++ pentru incrementare i -- pentru decrementare.
1
2
3
4
5

<?php
$foo=42;
$foo ++;
$foo --;
echo$foo , PHP_EOL ;

65

Dezvoltare web cu PHP

2.10. COMPLETRI

Aceti doi operatori pot pui att n faa variabilei, ct i n urma sa, aa cum am fcut n exemplul
de mai sus. Cnd sunt pui n faa variabilei, se numesc operatori de preincrement respectiv predecrement.
Cnd sunt pui dup variabil, ei poart numele de postincrement respectiv postdecrement.
Diferena dintre post- i pre- poate evideniat cu echo:
1
2
3
4

<?php
$the_answer =42;
echo $the_answer ++,' ';
echo $the_answer ;

Linia 3 mai nti evalueaz variabila, o aeaz cu echo, i apoi o incrementeaz. Faptul c ntr-adevr
variabila a fost incrementat se vede pe linia 4.
n schimb, n cazul operaiei pre-, mai nti se face incrementarea sau decrementarea, i apoi
rezultatul este pasat lui echo:
1
2
3
4

<?php
$the_answer =42;
echo++ $the_answer ,' ';
echo $the_answer ;

Decrementarea ntr-o bucl*


Partea I

Explic ce face urmtorul algoritm pas cu pas i ce reprezint rezultatul nal.


1
2
3
4
5
6
7

<?php
$the_answer =42;
$foo=0;
while ( $the_answer --){
$foo+= $the_answer ;
}
echo$foo;

Partea II
Modic codul din partea I astfel nct s foloseasc operatorul predecrement n loc de postdecrement,
ns rezultatul aat s e acelai.

2.10.4

Sfaturi de stil

Ceea ce ai pus la bucle precum while, do while, for, foreach sau constructe precum if/else/elseif/switch
ntre acolate ({ i }) se numete un bloc de instruciuni.
Dac un bloc de instruciuni consist dintr-o singur instruciune, atunci folosirea acoladelor pentru
a delimita blocul de instruciuni nu este necesar. Astfel, secvene de cod precum
1
2
3

if( $is_admin ){
echo'administrator ';
}

i
1
2
3

<?php
if( $is_admin )
echo'administrator ';

sunt complet echivalente din punct de vedere funcional.

66

Dezvoltare web cu PHP

2.10. COMPLETRI

Crearea de blocuri de instruciuni fr acolade, ca n exemplul anterior, este o practic proast.


Deseori se ntmpl s adaugi o nou instruciune, dar s uii s adaugi acoladele, ceea ce poate
duce la bug-uri greu de identicat.
Deci e mai bine s scrii codul din prima cu acolade chiar i acolo unde nu sunt necesare, pentru
a te feri de frustrrile cauzate de propriile tale greeli. i cu toii putem face astfel de greeli,
mai ales cnd suntem sub presiunea timpului sau suntem obosii.
Totui dou apsri de taste nu cost mult, iar avantajele primite merit efortul.

O alt tactic de a te feri de propriile greeli este s compari o constat cu o variabil, nu o variabil
cu o constant. Astfel, orict de obosit sau neatent ai , nu vei putea face greeli de genul
1
2
3
4
5

<?php
$rol='user ';
if($rol='admin '){
echo'estiadmin ';
}

Linia 3 ar executat astfel: atribuie valoarea admin variabilei $rol, i apoi veric dac variabila $rol
este evaluat ca TRUE.
Dup cum ai vzut n listingul 2.7, orice string diferit de este evaluat boolean ca TRUE, deci uxul
de execuie va trece mereu prin blocul de instruciuni al if-ului. Mult mai bine ar s scriem:
1
2
3
4
5

<?php
$rol='user ';
if('admin '=$rol){
echo'estiadmin ';
}

n astfel de cazuri, PHP ne va avertiza c nu putem atribui valoarea variabilei $rol unei valori constante
precum admin. Aceeai tehnic funcioneaz nu numai pentru valori constante, ci i pentru constante
simbolice declarate cu cuvntul cheie const.
Un alt sfat este s nu introduci variabile sau constante noi dect atunci cnd acestea chiar i au
rostul. Scopul unei variabile este s salveze n ea valori variabile, ce se pot schimba n timpul execuiei.
Dar asta nu e tot. Nu ar trebui s copiezi valorile unor variabile n alte variabile doar de dragul de a o
face. De exemplu, astfel de atribuiri nu i au rostul:
1

$nume = $input ;

deoarece $input conine deja inputul. Atribuirea ar avea rost doar dac ai face i o validare, de exemplu
cu type casting:
1

$cantitate =(int) $input ;

n astfel de cazuri nu copiezi pur i simplu valoarea dintr-o parte n alta, ci o i validezi, deci nu este o
copie perfect.
n afar de asta, copierea fr sens a unor valori dintr-o variabil n alta mnnc memorie RAM
degeaba, care de obicei e limitat.

2.10.5

Breaking down the logic

Fie conjuncia A && B cu tabelul de adevr 2.3.


ns aceast conjuncie folosit cu constructele if i else nu poate face diferena ntre ultimele 3
cazuri dintre cele 4 din tabelul anterior: toate vor acoperite de ramura else, dup cum se poate vedea
n listarea 2.8.
Ce facem ns dac vrem s tratm ecare dintre cele 4 cazuri individual? Simplu: ne folosim de
faptul c dac A i B este acelai lucru ca dac A i dac B, rescriind exemplul nostru ca n listarea 2.9.

67

Dezvoltare web cu PHP

2.10. COMPLETRI

Cazul nr
1
2
3
4

A
T
T
F
F

B
T
F
T
F

AB
T
F
F
F

Tabela 2.3: Tabelul adevrului pentru conjuncii

Listing 2.8: O singur conjuncie


1
2
3
4
5
6

if(A&&B){
// cazul TT=T
}
else{
// cazurile 2,3,4
}

Listing 2.9: Dup extinderea conjunciei


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

if(A){
if(B){
// cazul TT=T( cazul 1)
}
else{
// cazul TF=F( cazul 2)
}
}
else{
// oncewe 'reonthisbranch ,weknowthatAisFALSE ,butwhatabout B?
if(B){
// cazul FT=F( cazul 3)
}
else{
// cazul FF=F( cazul 4)
}
}

68

Dezvoltare web cu PHP

2.10. COMPLETRI

Breaking down the logic of a disjunction*

Creaz tabelul de adevr al disjunciei AB i rupe-i logica n prile componente dup tabelul creat,
ca n exemplul anterior.

2.10.6

Coding convention

Coding convention este un set de reguli de formatare a codului surs i de numire a identicatorilor
variabilelor, funciilor sau constantelor.
Avnd un astfel de set de reguli pe care toi programatorii l respect, codul surs devine mai uor de
neles i mentenat.
Exist cteva standarde larg rspndite, majoritatea avnd diferite viziuni despre ce nseamn cod
uor de neles i mentenat.
i Yet Another Project 18 are un astfel de standard. Acesta a fost deja folosit n mod consistent n
codurile surs prezentate pn acum. n continuare ne vom uita mai ndeaproape la aceast convenie.
1. identicatorii variabilelor sunt scrii cu litere mici, i ale constantelor cu litere mari
2. pentru contoare se folosesc identicatori scuri precum i sau j
3. acolada de deschidere a unui bloc de instruciuni este precedat de un spaiu; ea se a mereu pe
aceeai linie cu constructul (precum if, else, do) cruia i aparine
4. codul din interiorul unui bloc este indentat cu un tab
5. mrimea unui tab este de 4 spaii
6. acolada care nchide un bloc de instruciuni este aliniat vertical cu constructul corespunztor
7. dup virgula care separ diferite elemente (membrii unui array de exemplu) se a un spaiu
Un coding standard real ar avea o anvergur mult mai mare. Aceste mici reguli exist pentru a face
codul mai lizibil. n special punctul 6 are un impact mare:

Figura 2.5: Alinierea codului


Observi cum liniile 125 i 142 sunt aliniate vertical. La fel i 126 i 141. Astfel ochiului uman (cu
puin de antrenament) i este foarte uor s i dea seama care acolad cui aparine.
18

https://github.com/yet-another-project/phpro-book

69

Dezvoltare web cu PHP

2.11. INPUT I FORMULARE

n continuare, toate listrile vor respecta aceeai convenie de formatare a codului n mod consistent.
Nu vor mai introduse explicit unele convenii, ns este bine s i atent la aceste detalii pe msur ce
avansezi.
nc o mic convenie nescris: identicatorii foo i bar sunt folosii ca nlocuitori pentru ceva fr
semnicaie. n cazul lor, programatorul vrea s sublinieze c nu variabilele respective n sinea lor sunt
importante, ci alte concepte ataate lor.

Input i formulare
Atunci cnd utilizatorul introduce date, pe care le numim colectiv input, acele date trebuie salvate
n ceva pentru a avea acces la acele date. Iar cel mai la ndemn loc de a le salva sunt variabilele.
Una dintre variabilele n care PHP salveaz automat un anumit tip de input este $_GET . Pentru a o
popula cu valori, un utilizator trebuie s introduc ceva n request line-ul cererii HTTP.
Deci creaz un script get.php cu urmtorul coninut, ca s vezi ce conine variabila $_GET :
1
2

<?php
var_dump ( $_GET );

Apoi creaz o cerere HTTP cu telnet:


GET /get.php HTTP/1.1
Host: localhost
ntreaga comunicaie va arta cam aa:
GET /webdev/get.php HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Date: Sun, 06 Jun 2010 20:27:40 GMT
X-Powered-By: PHP/5.3.2
Content-Length: 13
Content-Type: text/html
array(0) {
}
Observm c $_GET este un array, i c are zero elemente. Altfel spus, e un array gol. Ceea ce e logic,
din moment ce nu pare s fcut niciun pas special pentru a introduce date. Pentru a introduce date
cu metoda GET, trebuie s crem parametri pe care s-i adugm la adresa resursei cerute. Sintaxa
general este:
'/path/to/script.php' ['?' <name> '=' <value> ['&' <name> '=' <value>]+ ]
n cuvinte: numele resursei este urmat de semnul ntrebrii, apoi o serie de una sau mai multe perechi
nume ia valoarea valoare, separate de caracterul ampersand (&).
Deci f cererea HTTP:
GET /get.php?foo=bar&answer=42
Vei vedea c $_GET are valoarea:

70

Dezvoltare web cu PHP

2.11. INPUT I FORMULARE

array(2) {
["foo"]=>
string(3) "bar"
["answer"]=>
string(2) "42"
}
Dup cum observi, nu e nimic special la $_GET , este un array asociativ cu care putem lucra aa cum
am lucrat cu toate array-urile de pn acum. Cheile din array sunt numele parametrilor, iar valorile
Valorile sunt mereu stringuri!
Asta nu este neaprat un lucru ru, PHP ne scap de necesitatea de a converti (cu type casting)
explicit atunci cnd detecteaz c poate face o conversie automat, ns mult mai bine este s convertim
noi toate inputurile.
PHP decide cum trebuie s converteasc anumite tipuri de date n alte tipuri de date n funcie de
contextul semantic n care punem acele date. De exemplu o valoare ABC n contextul semantic al unei
expresii booleene este evaluat ca TRUE.

Pentru a valida cu adevrat inputul, va trebui s folosim funcii, ns funciile vor prezentate
abia n capitolul 3. Deci deocamdat ne prefacem c un simplu type casting i cteva vericri
sunt suciente. Facem asta pentru a ne educa din start cu ideea necesitii validrii inputului.
Tehnici de validare complete vor prezentate dup introducerea funciilor.

Deci vom putea face un calculator care adun dou numere a i b introduse de utilizator, i aeaz
rezultatul adunrii:
1
2

<?php
echo(int) $_GET ['a'],'+',(int) $_GET ['b'],'=', $_GET ['a']+ $_GET ['b '];

Viziteaz adresa http://localhost/add.php?a=3&b=4.


Dar oare ce se ntmpl atunci cnd unul dintre parametri este inexistent? Hai s vedem. Viziteaz
direct http://localhost/add.php. PHP i va spune ce ai greit. Mesajul n browser este dicil de citit,
deci folosete opiunea view source a browserului tu. n refox, poi apsa CTRL+U .
PHP ne spune ceva de genul
Undefined index: a in add.php on line 2
pentru ecare acces la indexul (cheia) a respectiv b de pe linia 2. Astfel de mesaje ar putea utile
unui atacator care ar putea deduce din mesajele aate cam cum arat codul tu surs. Ar putea folosi
acele deducii pentru a-i sparge site-ul.
Din acest motiv vrem s vericm mai nti dac cheile a respectiv b exist ntr-adevr n $_GET
nainte de a accesa acei membri ai array-ului. Dac ambii membri a i b nu sunt prezeni, atunci
am un mesaj de eroare, altfel facem calculele, pentru c avem cu ce. n acest fel, orice ar introduce un
eventual atacator, acesta nu ar vedea informaii importante pentru el pe care noi nu vrem s le dezvluim
despre codul nostru surs:
Listing 2.10: Un calculator simplu
1
2
3
4
5
6
7

<?php
if (! isset ( $_GET ['a '])||! isset ( $_GET ['b '])){
echo'Introdu asib.';
}
else{
echo(int) $_GET ['a'],'+',(int) $_GET ['b'],'=', $_GET ['a']+ $_GET ['b '];
}

Dup cum tii, operatorul de negaie n PHP este !. El inverseaz practic valoarea de adevr a expresiei
logice care urmeaz. n cazul nostru inverseaz valoarea de adevr a constructului isset(), care are n
interior pe rnd parametrii $_GET['a'] respectiv $_GET['b'].
71

Dezvoltare web cu PHP

2.11. INPUT I FORMULARE

nelege expresia logic*


Partea I

Cum se citete linia 2 din listingul 2.10? ncepe rspunsul aa:


Dac .

Partea II
Rescrie condiia ntr-o form mai compact folosind legile lui De Morgan. Explic nc o dat cum
se citete aceast nou linie de cod, aa cum ai fcut n partea I a exerciiului pentru condiia iniial.

Mereu caut s-i rescrii expresiile logice cu ajutorul legilor lui De Morgan astfel nct s conin
ct mai multe conjuncii logice. Asta i va face scriptul mai rapid, deoarece ntr-o conjuncie
logic, de ndat ce s-a ntlnit o valoare FALSE, expresiile urmtoare din acea conjuncie nu
mai sunt evaluate, pentru c nu mai are rost: ntreaga conjuncie logic va avea oricum valoarea
de adevr FALSE.
Deci dac n exemplul nostru ar mai probabil s nu existe b, dar s existe a, atunci ar
mai bine s vericm mai nti dac b este setat. Asta ne-ar economisi nevoia de a-l verica
i pe a.
n exemplul nostru micu nu este neaprat cazul, ansele statistice ca un utilizator ruvoitor s
nu seteze ori a ori b sunt practic egale. ns reine aceast modalitate de optimizare pentru
situaiile mai complexe.
De exemplu, de preferat ar s verici mai nti unele variabile introduse de utilizator, i abia
apoi s verici conjunctiv valori dintr-o baz de date, deoarece operaiile precum cutrile n
baze de date sunt mult mai scumpe n termeni de performa.

Un calculator complet**

Creaz un script care accept doi parametri obligatorii a i b i un parametru opional op care ia
ca valori add, sub, mul, div sau mod pentru ecare dintre operaiile adunare, scdere, nmulire,
mprire i modulo.
Dac parametrul op nu este specicat, atunci trebuie s calculeze rezultatul tuturor operaiilor
a + b, a b, a b, a/b i a%b i s le aeze rezultatul. Dac este specicat, scriptul trebuie s calculeze
doar operaia corespunztoare i s-i aeze rezultatul.
Folosete constructul switch pentru a decide ce operaie trebuie s faci. Provocarea const n a nu
scrie cod repetitiv.
Cod repetitiv nseamn c ai o secven de una sau mai multe instruciuni identice n mai multe locuri
din algoritm.

2.11.1

Formulare, business logic i view logic

ns utilizatorul de rnd nu ar trebui s aib cunotine tehnice pentru a-i trimite date ctre
procesare. Pentru asta exist formulare HTML.
Numele cmpurilor de input (atributul name) vor folosite de browser pentru a genera URL-ul corect,
dac formularul este trimis prin metoda GET. De exemplu, un script de ntmpinare a vizitatorului ar
putea arta astfel:
1
2
3

<?php
$mesaj =NULL;
if(isset ( $_GET ['submit '])){

72

Dezvoltare web cu PHP

4
5
6
7
8
9
10
11
12
13
14
15
16
17

2.11. INPUT I FORMULARE

if(isset ( $_GET ['nume '])&& $_GET ['nume ']){


$mesaj ='Salut '. $_GET ['nume '];
}
else{
$mesaj ='Eroare :Nuai introdus numele .';
}
}
echo $mesaj ;
?>
<form method =" get">
<label for =" nume">Nume :</label >
<input type =" text"name =" nume"id =" nume"/>
<input type =" submit "name =" submit " value =" saluta -ma"/>
</form >

Scriptul este constituit din dou pri: liniile 2-10 se ocup de procesarea formularului. Liniile 11-17 se
ocup de generarea outputului pe baza datelor procesate.
Transmiterea de informaii din procesare ctre generarea de output se face folosind variabila
intermediar $mesaj. Deoarece ea va avea ca valoare un string, o iniializm cu valoarea NULL, pe
linia 2.
Dac condiia de pe linia 3 este adevrat, nseamn c utilizatorul a apsat butonul submit. n
acest caz, vrem s procesm formularul.
Indiferent dac formularul a fost trimis sau nu, am direct mesajul, care e NULL dac formularul
nu a fost trimis, deci nu rezult niciun output n urma executrii liniei 11, i asm i formularul.
Dac formularul nu a fost trimis, atunci cel mai probabil vizitatorul tocmai a intrat pe pagina noastr
i urmeaz s-l completeze i s-l trimit.
Linia 4 veric dac $_GET['nume'] este setat, i dac da, veric i dac valoarea salvat n el este
evaluat boolean ca ind TRUE. Altfel spus, veric i dac stringul nu este gol ('') sau nu are valoarea
0.
Dac toate acestea sunt adevrate, se genereaz o valoare dinamic ca mesaj de salut pe linia 5. Altfel
valoarea dinamic va un mesaj de eroare, iniializat pe linia 8.
Procesarea formularului de pe liniile 2-10 se numete i business logic. Acea secven din cod valideaz
inputul i seteaz variabila intermediar $mesaj n concordan cu acest input, sau cu absena inputului.
Variabila intermediar $mesaj salveaz n ea ceea ce numim informaie atomar a aplicaiei. Se
numete aa deoarece, cel puin n scriptul nostru, constituie o bucic de informaie indivizibil, de
sine stttoare.
Generarea outputului pe baza variabilelor intermediare (aici liniile 11-17) constituie view logic logica
de vizualizare.
Am putut genera output i direct pe liniile 5 respectiv 8, inclusiv formularul, ns separnd business
logic de view logic, putem modica i adapta mai uor scriptul la noi nevoi.
Logica din spatele aplicaiei nu are nimic de-a face cu modul ei de prezentare, iar asta ar trebui s e
reectat i de codul nsui. Una este validarea inputului, alta este aarea.
Mai trziu vei vedea c vei putea genera tot felul de formate de output, nu numai HTML, cu mai
mult uurin, deoarece business logic va rmne acelai, i va trebui doar s introduci un nou view logic
pe baza variabilelor intermediare pe care business logic i le pune la dispoziie.

Separ view logic de business logic i introdu variabile intermediare exact acolo unde este nevoie,
variabile care salveaz doar informaiile atomare de la baza aplicaiei.

73

Dezvoltare web cu PHP

2.12. ARRAY-URI MULTIDIMENSIONALE

View Logic i Business Logic*

mbuntete scriptul scris ca soluie la exerciiul Un calculator complet, adugnd un formular


care s e trimis prin metoda POST n loc de GET.
Datele trimise prin POST sunt puse de PHP n array-ul $_POST.
Separ business logic de view logic, exact ca n exemplul anterior, folosind variabile intermediare.

Dei poi salva valori n array-uri precum $_GET sau $_POST, nu este bine s o faci. Array-uri
ca acestea sunt gndite pentru a prelua input de la utilizator, sunt populate automat de PHP.
Altfel spus, ele au semantica de input, deci nu ar trebui s le ncalci semantica salvnd datele
tale proprii n ele.

Array-uri multidimensionale
Array-urile sunt structuri de date compozite n care putem salva valori. ns un array nsui este o
valoare. Din asta deducem inductiv c putem avea array-uri n array-uri.
Un array bidimensional are dou dimensiuni, i ar putea iniializat astfel:
1
2
3
4
5
6
7

$array_2d = array (
array ('foo ') ,
array ('bar ')
);
echo'<pre >';
var_dump ( $array_2d );
echo '</pre >';

Bineneles c putem refolosi variabile n care am salvat anterior array-uri pentru a crea noi array-uri.
De exemplu, un array tridimensional ar putea arta astfel:
1
2
3
4
5

$array_3d = array (
'one '=>$array_2d ,
'two '=> $array_2d
);
var_dump ( $array_3d );

Putem crete orict n dimensiuni, sau putem chiar avea un array cu dimensiuni variabile:
1
2
3
4
5
6
7

<?php
$array_multidim = array (
$array_2d ,
array (' inner 2d'=>$array_2d , $array_3d ),
$array_2d
);
var_dump ( $array_multidim );

Dup cum tii deja, array-urile sunt ndeosebi utile atunci cnd vrem s procesm anumite date cu
acelai (sub)algoritm.
Un exemplu pragmatic ar s-i cerem utilizatorului s bifeze fructele sale preferate, i pe baza lor s
am anumite informaii despre ele.
n formularul HTML nu va trebui dect s numim cmpurile de input cu [], exact aa cum am
accesa i array-urile n PHP. Pentru o serie de checkbox-uri am putea avea:
1
2
3
4

<form method ="POST">


<input type=" checkbox "name=" fructe []"value ="mere"/>
<input type=" checkbox "name=" fructe []"value ="pere"/>
</form >

74

Dezvoltare web cu PHP

2.12. ARRAY-URI MULTIDIMENSIONALE

Am putea i denumi acele intrri dac n PHP semantica datelor nu este de o niruire, ci un set de date
asociative:
1
2
3
4

<form method ="POST">


<input name=" fructe [mere]"/>
<input name=" fructe [pere]"/>
</form >

Un exemplu complet pentru un astfel de script ar putea arta astfel:


Listing 2.11: Fructe favorite
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15

16

17
18

<?php
$fructe = array (
'mere '=>'Merele contin multi antioxidanti .',
'pere '=>'Perele sunt bogate in vitamina Csiin potasiu .',
'alune '=>'Alunele sunt bogate inproteine , grasimi nesaturate si vitamina B6.'
);
if(isset ( $_GET ['submit '])&& isset ( $_GET ['fructe '])){
foreach ( $_GET ['fructe ']as $fruct ){
echo'<p>', $fructe [ $fruct ],'</p>';
}
}
?>
<form method =" GET">
<input type =" checkbox "name =" fructe []"value =" mere"id =" mere -id"/><label for =" mere -id
">Mere </ label >
<input type =" checkbox "name =" fructe []"value =" pere"id =" pere -id"/><label for =" pere -id
">Pere </ label >
<input type =" checkbox "name =" fructe []"value =" alune "id =" alune -id"/><label for =" alune
-id">Alune </ label >
<input type =" submit "name =" submit " value =" Trimite "/>
</form >

Liniile 14-16 sunt foarte repetitive, i dei putem proceda ca n exemplul de mai sus punnd cte un
checkbox, un label, i o intrare n array-ul $fructe care conine informaiile efective, acest lucru e foarte
inecient i mnnc timp dac vrem s personalizm acest script.

Cnd ai linii de cod repetitive foarte asemntoare din punct de verede structural, cel mai
probabil poi face acele lucruri ntr-o bucl. Folosete aceste bucle pentru a reduce costurile
de mentenan (i modicare) a codului, deci implicit i pentru economisirea timpului. Astfel
devii mai productiv.

Ce se ntmpl dac vrem s adugm sau s tergem un fruct? Trebuie s o facem n trei locuri!
Practic ns avem toate informaiile de care avem nevoie (lista de fructe posibile) n array-ul $fructe,
deci putem folosi acele informaii pentru a genera formularul HTML.

75

Dezvoltare web cu PHP

2.12. ARRAY-URI MULTIDIMENSIONALE

Structuri de date abstracte*

Modic scriptul din listingul 2.11 astfel nct s genereze dinamic formularul HTML pe baza
structurii de date asociative $fructe.
mbuntete scriptul astfel nct s nu dea erori pentru inputuri precum
/fructe.php?fructe[]=capsuni&submit=Trimite

Dup cum observi, deja ai nvat o grmad de lucruri care i pot uura munca i economisi
timp i i ofer i exibilitate.
Tot ce trebuie acum s faci e s reectezi asupra lucrurilor nvate i s i imaginezi cum le-ai
putea combina.
Ai la dispoziie variabile i structuri de date, ramicri condiionale ale uxului de execuie, i
bucle.

2.12.1

Geometria i normalizarea array-urilor

Geometria unui array descrie felul n care arat un array. O caracteristic a geometriei este numrul
de dimensiuni a array-ului i/sau a ecrui cmp.
De exemplu putem stabili c un cmp pasiuni este o list de pasiuni, deci pe undeva n aplicaie
putem avea:
1

$pasiuni = array ('tenis ','fotbal ','balet ');

Structurile19 de date pot crete ns n complexitate, de exemplu putem descrie o persoan cu


urmtoarea list de meta-date:
1
2
3
4
5
6

$persoana = array (
'nume '=>'Xulescu ',
'varsta '=>15,
'liceu '=>'George Enescu ',
'pasiuni '=> array ('tenis ','fotbal ','balet ')
);

Meta-datele precum nume sau pasiuni sunt xe, dar valorile pot varia de la om la om. Cert este c un
cmp varsta va mereu integer, iar pasiuni va mereu un array.
Dar ce se ntmpl dac o persoan nu are pasiuni? Simplu: lista de pasiuni poate goal:
1
2
3
4
5
6

$persoana = array (
'nume '=>'Xulescu ',
'varsta '=>15,
'liceu '=>'George Enescu ',
'pasiuni '=> array ()
);

n acest fel, chiar dac nu avem pasiuni, structura de date n ntregimea sa respect n continuare
geometria prestabilit a array-ului.
Ce se ntmpl dac n cadrul aplicaiei noastre stabilim i c o persoan poate avea i caracteristici
precum facultate sau limbi_cunoscute? Va trebui s adugm i aceste caracteristici, pentru a pstra
array-ul normalizat, chiar dac persoana respectiv nu are o anumit facultate drept caracteristic.
Obinem:
1
2
3
4
19

$persoana = array (
'nume '=>'Xulescu ',
'varsta '=>15,
'liceu '=>'George Enescu ',
Array-urile

76

Dezvoltare web cu PHP

5
6
7
8

2.13. SISTEME DE NUMERAIE

'facultate '=>NULL ,
'limbi_cunoscute '=> array ('romana ') ,
'pasiuni '=> array ()
);

Atunci cnd aducem o structur de date la cea mai complex form a sa, spunem c am normalizat
acea structur, sau c am adus-o la o form canonic.

Sisteme de numeraie
2.13.1

Baze numerice

Pentru a nelege operaiile binare, trebuie s nelegem mai nti sistemele de numeraie.
Primul sistem de numeraie pe care l-ai nvat i cu care te simi cel mai confortabil este sistemul
decimal. Se numete astfel deoarece ai la dispoziie zece simboluri, ecare din ele reprezentnd o cantitate:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Trebuie s facem ns distincia clar ntre cantitate i reprezentarea acesteia. n cazul nostru,
cantitatea doisprezece are reprezentarea 12.
Dar ce se ntmpl cnd numrm? Cum numrm de fapt? Ai nvat asta cnd erai copil i i-a
intrat att de adnc n procesele cognitive, nct nici nu mai poi contientiza ce faci cnd numeri de
fapt.
Cnd numeri, iei pe rnd simbolurile pe care le ai la dispoziie 0, 1, 2, 3, 4, 5, 6, 7, 8. O dat ajuns
la 9, nu mai ai simboluri, deci adaugi unu la poziia imediat din stnga, i nc unul la poziia la care
eti, n cazul nostru la poziia unitilor.
Asta e posibil deoarece reprezentarea
9
este acelai lucru cu
09
sau cu orici de 0 n fa, nu conteaz:
00000009
Deoarece dup ultimul simbol, n cazul nostru 9, urmeaz primul simbol, deci 0, i invers, deoarece
naintea lui 0 se a simbolul 9, spunem c acest ir de simboluri 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, este un ir
circular. Ca o analogie la ce nseamn circular, gndete-te la un lact cu cifru. Aa se face c dup 009
urmeaz 010, adic zece.
Pn acum am numrat n baza 10. Acum hai s generalizm. S zicem c avem simbolurile s,t,u,v,
i vrem s numrm cresctor n baza 4, deoarece avem patru simboluri. Pentru asta nu trebuie dect
s lum simbolurile la rnd: s, t, u, v. O dat ajuni la v, nu mai avem simboluri, deci trebuie s srim
pe poziia urmtoare i s adugm cantitatea 1.
Cum pe poziia urmtoare se a s (similar cu acel 0 invizibil din baza 10), i deoarece dup v
urmeaz s, deducem c dup v urmeaz ts, care reprezint deci cantitatea 4. n continuare ar urma tt,
tu, tv, us, ut, uu, uv, , vv, , tss, tst, tsu, tsv, tts, ttt, , vvs, vvt, vvz, vvv, tsss,

77

Dezvoltare web cu PHP

2.13. SISTEME DE NUMERAIE

Numr n baza apte**

Numr pn la cantitatea dou zeci n baza apte folosind setul de simboluri ordonate d, g, h, a, s,
z, u.
Orice baz de numeraie, e ea binar (2), octal (8) sau hexadecimal (16) funcioneaz dup exact
aceleai principii.
Demn de menionat este c n PHP, valorile pot introduse folosind reprezentarea lor octal punnd
zero n faa lor, iar valorile hexadecimale pot introduse direct prexndu-le cu 0x. Pentru reprezentarea
hexadecimal se folosesc pe rnd literele A, B, C, D, E, F care urmeaz dup simbolul 9. Exemple:
1
2
3

<?php
$foo=052;
echo$foo ,'',0x2A;

2.13.2

Operaii pe bii

Exist ase operaii binare n PHP, iar nelegerea lor este foarte uoar dac ai neles deja expresiile
booleene i operaiile logice prezentate n paginile 4447.
Plecnd de la reprezentarea binar a dou cantiti, de exemplu 00101010 i 01100111, putem uni
conjunctiv ecare bit cu bitul corespunztor din a doua valoare. 1 este acelai lucru cu TRUE iar 0
acelai lucru cu FALSE din tabelul 2.2. Aceast operaie se numete binary and, iar operatorul PHP este
&. Calculm:
00101010 &
01100111
-------00100010
Operaia disjunctiv se numete binary or, i are operatorul |. Calculm:
00101010 |
01100111
-------01101111
Mai putem muta i la dreapta irul de bii cu un numr de poziii. Operatorul pentru asta este >>
i se numete shift to right. Exemplu:
00101010 >> 3 = 00000101
Un octet (en. byte) este un ir de opt bii, iar un bit este 0 sau 1. n exemplele de mai sus am fcut
deci operaiile binare and i or pe reprezentarea ntr-un byte a doi operanzi.
n PHP, numerele ntregi ocup un anumit numr de bytes. Acesta este dependent de platform, i
este de obicei 4 sau 8. A ct spaiu au la dispoziie numerele ntregi:
1
2

<?php
echo PHP_INT_SIZE , PHP_EOL ;

Acum tim tot ce trebuie pentru a aa reprezentarea binar a oricrui numr:


Listing 2.12: Aarea bit cu bit a unui int
1
2
3
4
5

<?php
$a=42;
for($i =8* PHP_INT_SIZE -1;$i >=0;$i --){
echo($a >>$i)&1? '1':'0';
}

78

Dezvoltare web cu PHP

2.13. SISTEME DE NUMERAIE

n urma operaiei shift to right cu X bii, se pierd cei mai din dreapta X bii, iar n partea din
stnga X bii (care apar noi) sunt iniializai cu zero n cazul numerelor pozitive, iar n cazul
numerelor negative cu unu.

Cum funcioneaz aarea bit cu bit a unui int?***

Explic cum funcioneaz codul din listingul 2.12.


Concentreaz-te n special pe expresia ($a>>$i) & 1.
Experimenteaz i f observaii pe baza experimentelor. Ai putea citi i articolul de pe wikipedia.20
Analog cu shift to right, exist i un shift to left. Operatorul este <<, dup cum poi vedea n listingul
2.13.
Listing 2.13: Operatorul shift to left
1
2
3
4
5
6
7
8
9
10

<?php
$a=42;
for($i =8* PHP_INT_SIZE -1;$i >=0;$i --){
echo($a >>$i)&1? '1':'0';
}
$a <<=5;
echo PHP_EOL ;
for($i =8* PHP_INT_SIZE -1;$i >=0;$i --){
echo($a >>$i)&1? '1':'0';
}

Dup cum observi pe linia 6, putem contracta operaiile binare cu operaia de atribuire ntr-o singur
operaie.
Similar cu shift to right, biii din dreapta sunt iniializai automat cu 0, iar cei din stnga se pierd.
O alt operaie este inversarea sau negarea biilor. 0 devine 1, iar 1 devine 0. n contrast cu operaiile
de pn acum, inversarea biilor21 are un singur operand. Operatorul este i se pune n faa operandului:
1
2
3
4
5

<?php
$a=42;
for($i =8* PHP_INT_SIZE -1;$i >=0;$i --){
echo($a >>$i)&1? '1':'0';
}

6
7
8
9
10
11

echo PHP_EOL ;
$a=~42;
for($i =8* PHP_INT_SIZE -1;$i >=0;$i --){
echo($a >>$i)&1? '1':'0';
}

Ultima operaie binar este exclusive or, sau pe scurt xor. Operatorul este ^, i accept doi operanzi.
n algebr boolean, am descrie aceast operaie aa:
(a b) (a b)

20
21

http://en.wikipedia.org/wiki/Bitwise_operation
La fel ca negarea boolean, unde !<expr> are valoarea de adevr invers a expresiei.

79

Dezvoltare web cu PHP

2.14. VARIABILE VARIABILE

Jongleaz cu expresii boolene***

Explic n limba romn, pe baza deniiei operaiei xor (a b) (a b), n ce situaii este foarte
util aceast operaie.

Operaii pe bii

Creaz un script care accept dou numere a i b, cu b mai mic sau egal cu 8*PHP_INT_SIZE-1, i
care aeaz rezultatele operaiilor a&b, a|b, a<<b, a>>b, a^b, ~a, ~b i (a>>b)&0x1.
Operaiile pe bii sunt foarte utile atunci cnd vrem s setm atribute booleene da sau nu pentru
anumite proprieti, drepturi de acces, etc. Avantajul este c aceste cmpuri de bii (en. bitelds) sunt
foarte compacte, ocup puin spaiu.
Un scenariu de utilizare:
1
2
3
4
5

<?php
const AUTH_NONE =0x00;
const AUTH_READ =0x01;
const AUTH_WRITE =0x02;
const AUTH_DELETE =0x04;

6
7

$drepturile_mele = AUTH_READ | AUTH_WRITE | AUTH_DELETE ;

8
9
10
11

if( $drepturile_mele & AUTH_READ && $drepturile_mele & AUTH_WRITE ){


echo'poticitisiscrie <br >';
}

Liniile 2-5 iniializeaz constante cu drepturile respective. Cantitile 1, 2 i 4 au ecare biii doar cte
un bit setat, de la dreapta la stnga, 1 are primul bit setat, 2 are al doilea bit setat, 4 l are doar pe al
treilea setat. Astfel nu avem conicte ntre cele patru niveluri de acces. Folosim constante deoarece acei
bii nu se schimb niciodat.
Linia 7 unete disjunctiv toate drepturile de acces, ceea ce rezult practic n irul de bii 00000111.
Linia 9 veric conjunctiv dac drepturile utilizatorului care viziteaz momentan pagina include i
bitul AUTH_READ. Dup evaluarea condiiei de pe linia 9 ne alegem e cu valoarea 0, e cu o alt
valoare, care conform observaiilor pe care le-ai fcut n listingul 2.7 va evaluat ca TRUE.
Teoretic am putut folosi i un array asociativ, de exemplu:
1
2
3
4
5
6
7
8
9

<?php
$drepturile_mele = array (
'read '=>TRUE ,
'write '=>TRUE ,
'delete '=>TRUE
);
if( $drepturile_mele ['read ']&& $drepturile_mele ['write ']){
echo'poticitisiscrie <br >';
}

ns ocup mult mai mult spaiu i nu este la fel de compact. n plus, biteld-urile pot salvate mult
mai uor n alte sisteme precum baze de date, poi sorta dup anumite valori, .a.m.d.

Variabile variabile
O variabil variabil se numete astfel deoarece i construim numele (identicatorul) variabil, pe baza
altor valori. Pentru a crea o variabil variabil, folosim $, urmat de identicatorul unei variabile, care
80

Dezvoltare web cu PHP

2.15. REFERINE

dup cum tim, ncepe tot cu $. Deci ne alegem cum dou simboluri $$ unul dup altul.
Exemplu:
1
2
3
4

<?php
$a='b ';
$$a='c ';
var_dump ($b);

Dup cum observi, nu declarm nicieri o variabil $b, ns o folosim pe linia 4. Variabila $b este creat
pe linia 3, pe baza valorii variabilei $a.
Putem chiar crea variabile din array-uri asociative, de exemplu:
Listing 2.14: Variabile variabile din array asociativ
1
2
3
4
5
6
7
8
9

<?php
$variabile = array (
'foo '=>'bar ',
'foobar '=>'barfoo '
);
foreach ( $variabile as $nume => $valoare ){
$$nume = $valoare ;
}
echo"$foo $foobar ";

Atunci cnd crem o variabil (variabil sau nu, nu conteaz), PHP i pune identicatorul i valoarea
ntr-un tabel. Acest tabel se numete scopul global de variabile (en. variable global scope).
Folosind variabile variabile, polum acest scope, iar asta este o practic rea. Exist unele situaii
n care variabilele variabile sunt utile, dar acestea implic alte scope-uri, nu cel global. Un astfel de
exemplu22 l vom ntlni n capitolul urmtor.

Referine
Dup cum tii, variabilele create sunt salvate de PHP ntr-un tabel cu identicatorul i valoarea
variabilei.
Referinele sunt ca nite nume alternative pentru aceeai valoare. Pentru a crea o referin, punem
& n faa identicatorului variabilei pe care vrem s o refereniem. Exemplu:
1
2
3
4
5
6

<?php
$a=42;
$b=&$a;
echo$a ,' ';
$b ++;
echo$a;

Conform liniei 3, identicatorul $b va arta cu degetul (en. point at) ctre coninutul variabilei $a. Pe
linia 5 incrementm acea valoare, ns prin prisma identicatorului $b.
Din moment ce i $a, i $b, arat ctre aceeai intrare din tabelul scope-ului global, lucrul care se
reect i asupra valorii variabilei $a pe linia 6.

Exerciii
22

i singurul n care folosirea variabilelor variabile este legitim, dup prerea autorului.

81

Dezvoltare web cu PHP

2.16. EXERCIII

Terminologie*

n acest capitol ai nvat o grmad de termeni noi. Folosind cuprinsul de la pagina 5, ia ecare
seciune a acestui capitol la rnd, i la ecare scrie cel puin un cuvnt sau expresie, e el n romn sau
n englez. La termenii n romn, scrie i corespondenii englezeti.
Gndete-te ct tiai nainte de a citi acest capitol. Cum te simi? Eu m-a simi mndru. Felicitri!

Rezumat**

Explic n cel puin 500 de cuvinte cum funcioneaz lucrurile pe care le-ai nvat i neles n acest
capitol. Folosete propriile formulri (fr copy/paste), i folosete ct mai muli termeni pe care i-ai
gsit n exerciiul anterior.
ncearc s sintetizezi ct mai multe lucruri care nu au fost spuse explicit, dar pe care le poi deduce.
F brainstorming23 cu tine nsui, analizeaz conceptele pe care le explici n rezumat.
ncearc s te gndeti ct mai serios i s reectezi asupra celor nvate. De exemplu, gndete-te i
explic ce legtur are conceptul de context semantic cu restul noiunilor nvate n acest capitol (spre
exemplu noiunea de expresie n PHP, e ea boolean, matematic, sau cu stringuri).
Nu te teme s faci armaii ndrznee pentru a arta c tii s gndeti out of the box, deci c ai
potenialul de a inovativ. Chiar dac armaiile vor greite, este foarte probabil s nvei lucruri
noi, pentru c-i faci pe tutorii phpro s te corecteze i automat s vin cu explicaii din care s nvei
lucruri noi, sau care i claric unele lucruri. Sau cine tie, poate ai o ntrebare a crei rspuns e att
de complex nct i blochezi pe tutori :-)

Language Reference

Acest capitol a ncercat s i ofere o imagine ct mai clar a conceptelor de baz, ns e foarte probabil
ca unele noiuni ori s nu fost abordate cu destul de mult atenie la detalii, ori s nu fost abordate
deloc.
PHP este documentat foarte bine n ceea ce numim manualul PHP. Adresa sa ocial este http:
//php.net/manual.
Intr pe manualul PHP i urmeaz cu atenie toate paginile din capitolul Language Reference.24

Citete exclusiv versiunea englez a manualului. Este cea mai actual i cea mai corect
versiune. NU citi traducerea sa n romn. Astfel te vei i obinui s lucrezi cu engleza,
ca un viitor profesionist.

Gsete cel puin 5 lucruri care nu au fost spuse n carte i pe care le-ai putut nelege n urma citirii
acelui capitol din manual.

23
24

http://en.wikipedia.org/wiki/Brainstorming
http://php.net/langref

82

Dezvoltare web cu PHP

2.16. EXERCIII

Scrie scripturi
Partea I

Scrie trei scripturi, ecare de cel puin 50 de LOCs,25 care s aib n total peste 250 de LOCs, i s
rezolve probleme practice sau care te-au preocupat mereu sau probleme pe care i le-ai pus pe parcursul
studiului acestor capitole.
Scripturile trebuie s genereze cod XHTML 1.1 curat, i s e validate cu succes de validatorul W3C.26
Fi atent i la accesibilitatea formularelor i genereaz cod XHTML semantic. Nu uita s separi
business logic de view logic i s foloseti variabile intermediare.
Posibile probleme de rezolvat:
genereaz un tabel HTML pe baza unui array bidimensional asociativ i aeaz rndurile din tabel
colorate alternativ cu dou culori de fundal, pentru o mai bun accesibilitate
citete o sum de bani (RON) i aeaz numrul minim de bancnote din ecare sum: 1, 5, 10,
50, 100, 200, 500, cu care poi acoperi suma introdus
Cere ajutorul comunitii de pe phpro acolo unde te blochezi.

Partea II
Explic pas cu pas unui neprogramator ce face ecare cod i cum o face. Nu ai voie s foloseti
termeni tehnici, ci doar formulri pragmatice.

25
26

Liniile goale sau care consist doar din comentarii nu se calculeaz


http://validator.w3.org/

83

Capitolul

Reutilizarea i modularizarea codului


Acest capitol i va prezenta tehnici de reutilizare a codului, ceea ce-i va permite s programezi mai
ecient. i va mai deschide porile i ctre mai toate funcionalitile i capacitile limbajului PHP.

Funcii
3.1.1 Funcii proprii. Termeni generali
O funcie este ca o cutie neagr. O hrneti cu date prin intermediul a ceea ce numim parametri, i
ea face anumite operaii pe acel input primit prin parametri.
Unele funcii genereaz output, alte funcii returneaz valori i nu aeaz nimic, iar altele nici nu
accept parametri.
Pn acum am ntlnit o singur funcie, var_dump(). Ea accept un singur parametru,1 care trebuie
s e o expresie, i genereaz ca output valoarea acelei expresii, alturi de tipul de date al expresiei.
Deoarece tipul de date al parametrului acceptat de aceast funcie nu trebuie s e de un anumit
fel specic, ci poate avea de la dou tipuri de date n sus, spunem c parametrul funciei este de tipul
mixed. Acesta nu este un tip de date existent n PHP, este doar felul n care putem documenta astfel de
valori care pot avea tipuri de date multiple.
Documentarea funciei var_dump() ar putea arta deci astfel:
void var_dump(mixed $expression)
- dumps information about an expression
var_dump se numete identicatorul sau numele funciei. Acel void din faa lui ne spune ce fel de date
returneaz funcia. void este un alt tip de date care de fapt nu exist i este folosit doar n documentarea
funciilor. void nseamn nimic, deci n cazul nostru, nseamn c funcia nu returneaz nimic.
Dar cum crem propriile funcii? Hai s crem o funcie care nu accept nici un parametru, care nu
returneaz nimic, dar care doar face ceva. Hai s i dm acestei funcii identicatorul foo. Documentarea
ei va arta deci astfel:
void foo(void)
Aceast documentare se numete i semntura funciei, deoarece ne spune cum arat din exterior acea
funcie, ce fel de parametri accept i n ce ordine, i ce fel de date returneaz.
Limbajul PHP nu este att de strict n privina tipurilor de date acceptate ca parametri sau tipurilor
de date returnate de funcii. De aceea documentarea semnturilor funciilor noastre ne poate feri pe noi
1

Greeal deliberat. Voi reveni la lecia despre funcii variadice.

84

Dezvoltare web cu PHP

3.1. FUNCII

nine de greeli de programare. De exemplu, dac documentm o funcie ca returnnd int, i la un


moment dat, n timp ce implementm acea funcie, returnm un string, atunci e clar c am fcut o
greeal, i cel mai probabil greeala este n implementaie.

Atunci cnd decizi s creezi o funcie, mai nti analizeaz logistica care impune necesitatea
acelei funcii, documenteaz de ce exist acea funcie, ce face, i semntura sa. Dup aceea
implementeaz funcia astfel nct s respecte documentaia sa.

Pe lng o semntur, o funcie mai are i o implementaie. Toate funciile trebuie implementate
nainte de a folosite. Pentru a declara implementaia unei funcii n PHP,2 scriem cuvntul cheie
function urmat de identicatorul funciei, paranteze rotunde, i ntre ele o list a eventualilor parametri,
apoi implementaia efectiv a funciei ntre acolade, ca un bloc de instruciuni. Funcia noastr foo ar
putea avea urmtoarea implementaie:
<?php
function foo (){
echo'bar ';
}

1
2
3
4

Dac semntura funciei se pune n documentaia funciei, atunci analog cu ea avem n codul PHP efectiv
ceea ce numim antetul funciei (en. function header), n exemplul anterior acesta ind
foo()
Acum c am implementat funcia, o putem apela. Un exemplu complet:
<?php
function foo (){
echo'bar ';
}
foo ();
$i =10;
while ($i --){
foo ();
}

1
2
3
4
5
6
7
8
9

Pe liniile 5 i 8 spunem c am apelat funcia foo, care poart numele de callee sau apelat.
Dup cum observi, poi folosi constructele nvate n capitolul anterior n jurul funciilor. La fel
de bine poi folosi constructele respective i n implementaia funciilor. De exemplu, aceast funcie
aeaz numerele de la 0 la 10:
<?php
function count_to_10 (){
for($i =0;$i <=10; $i ++){
echo$i ,' ';
}
}
count_to_10 ();

1
2
3
4
5
6
7

Funciile pot accepta i parametri. Putem spune c am parametrizat funcia sau c am parametrizat
algoritmul implementat de acea funcie. Parametrii adaug un plus de exibilitate.
Ce se ntmpl dac vrem s numrm de la 0 la un numr variabil? Algoritmul nu se schimb, numai
c trebuie s ncepem de la 0 dar s ne oprim la acel numr specicat n parametru. Exemplu:
<?php
function count_to_n ($n){
for($i =0;$i <= $n;$i ++){
echo$i ,' ';
}

1
2
3
4
5
2

Sau pe scurt: pentru a implementa o funcie

85

Dezvoltare web cu PHP

6
7
8

3.1. FUNCII

echo'<br/>';
}
count_to_n (42);

Iar documentaia funciei ar arta aa:


void count_to_n(int $n)
Acel int $n ne spune c funcia accept un parametru care va accesibil din interiorul funciei sub
identicatorul $n, i c tipul de date al acestuia este integer. n interiorul funciei putem face orice dorim
cu acel parametru.
Sau am putea lsa la o parte identicatorul parametrului n documentaie:
void count_to_n(int)
Asta este posibil deoarece la documentarea funciei nu conteaz numele parametrului. Numele
parametrului este util doar n implementaia funciei, ns noi acum doar documentm semntura funciei,
iar n documentaie nu trebuie s tim dect ce tip de date are al X-ulea parametru (aici primul).
n practic ns, este mai bine s spunem i numele parametrului n documentaie, deoarece putem
folosi acel identicator al parametrului n descrierea funcionalitii funciei.

Documenteaz-i mereu semnturile funciilor tale, cu tot cu tipurile de date ale parametrilor.
Asta te va ajuta s-i aminteti mai repede cum funcioneaz propriul tu cod chiar i dup ani
de zile n care nu ai lucrat cu acele funcii proprii.

Pentru a documenta o funcie, scrie-i semntura deasupra implementriii, folosind comentarii. Tot n
acele comentarii poi documenta i ce face ecare parametru. Exemplu de cod documentat bine:
1
2
3
4
5
6
7
8
9
10
11
12

<?php
/**
* display aspace - separated listofnumbers ,upto$n
*
*void count_to_n (int$n)
*/
function count_to_n ($n){
for($i =0;$i <= $n;$i ++){
echo$i ,' ';
}
echo'<br/>';
}

ncearc s apelezi funcia aa, i observ ce se ntmpl:


1

count_to_n ('foo ');

Cu ajutorul documentaiei, i-ai putea da seama uor care e greeala, chiar dac acel cod este scris de
altcineva i l vezi pentru prima dat. ntr-un capitol urmtor vei vedea c exist i scule care genereaz
semi-automat documentaie n format HTML, care i fac navigarea prin cod mai uoar, i care-i permit
s nelegi cu uurin cum funcioneaz aplicaii complexe, chiar dac acestea i sunt strine.

Funcie care aeaz reprezentarea binar

n capitolul trecut a trebuit s scrii de ecare dat o bucl atunci cnd ai vrut s aezi reprezentarea
binar a unui numr ntreg. Cu funcii, nu trebuie s implementezi acel algoritm dect o singur dat,
s l mbraci ntr-o funcie, i s apelezi acea funcie de ecare dat cnd ai nevoie de ea. Asta te scap
de mult munc inutil i cod care nu numai c este repetitiv, dar care mai este i greu de citit.
Scrie o funcie care aeaz reprezentarea binar a unui integer.

86

Dezvoltare web cu PHP

3.1. FUNCII

Arile fcute n funcii sunt puternice i ne scap deja de mult efort. ns nainte de a ne grbi s
punem o grmad de echo n funciile noastre, hai s ne ntrebm nainte:
Ce se ntmpl dac nu vrem s am rezultatul unei funcii, ci s-l refolosim ntr-un alt mod?
Ce se ntmpl dac nu vrem de exemplu s am reprezentarea binar a unui numr, ci s o salvm
ntr-un ier, o baz de date, sau s o trimitem prin e-mail?
Retval comes to the rescue. Retval, sau corect return value, este valoarea returnat de o funcie.
Toate funciile pot returna o valoare.
n mod implicit, funciile care returneaz void, deci care n fapt nu returneaz nimic, returneaz de
fapt valoarea NULL. Exemplu:
<?php
function do_nothing (){
// thedo - nothing function isa function
// which hasa simple functionality :itdoes nothing
}
$val= do_nothing ();
var_dump ($val);
var_dump ( do_nothing ());

1
2
3
4
5
6
7
8

Pe linia 6, atribuim valoarea returnat de apelul la do_nothing() variabilei $val, i pe linia urmtoare
am aceast valoare.
Pe linia 8 i pasm ca parametru lui var_dump() direct retval-ul apelului la do_nothing().

Valoarea returnat de o funcie este tot o valoare (dup cum i spune nsi numele de return
value), deci poate folosit ca atare peste tot unde parserul PHP accept o valoare.

Deoarece o valoare este i o expresie, putem pune un apel la o funcie peste tot unde PHP accept o
expresie: n condiiile buclelor, ntre [] pentru a accesa un anumit index al unui array, .a.m.d. Exemplu:
if( do_nothing ()){
echo'do nothing returns something ';
}

1
2
3

Fluxul de execuie va ajunge la if. O dat ajuns aici, PHP tie c trebuie s citeasc o expresie i s o
evalueze boolean, deci ntlnete apelul la o funcie. Deoarece e un apel, funcia se numete i apelat, iar
uxul de execuie trebuie s intre n acea funcie, s treac prin implementaia funciei,3 i ntr-un nal
s se ajung la un retval, care n cazul nostru este implicit NULL.
Apoi acest retval este pasat napoi apelantului (en. caller),4 n cazul nostru contextului semantic de
valoare boolean creat de constructul if. O dat ajuns n acest context, NULL-ul returnat de funcie este
evaluat ca FALSE.
Fiind ntr-o funcie, pentru a returna o anumit valoare n loc de NULL-ul implicit, trebuie s folosim
constructul return. Sintaxa este simpl i intuitiv:
return <expr>;
n capitolul trecut am auzit despre scope-ul global al variabilelor. Cu ajutorul funciilor, putem vedea
n practic ce nseamn acest scope i ce altfel de scope-uri mai exist.
Vom discuta pe marginea urmtorului listing:
<?php
function increment ($a){
$a='bar ';
echo"in interior \$aeste$a\n";
}
$a=42;

1
2
3
4
5
6
3

Altfel spus, s apeleze funcia.


Apelantul este entitatea care apeleaz funcia. n cazul nostru, este scriptul .php nsui, dar ar putea i o alt funcie,
deoarece o funcie poate apela o alt funcie.
4

87

Dezvoltare web cu PHP

7
8
9

3.1. FUNCII

echo"$a\n";
increment ($a);
echo"$a\n";

Totul ne este cunoscut pn la linia 8. La apelarea funciei increment(), parametrul $a al funciei


primete iniial valoarea 42, aa cum ne ateptm. ns uxul de execuie ajunge pe linia 3, moment n
care $a primete valoarea constant bar, aa cum ne demonstreaz i outputul generat pe linia 4. Totui
uxul de execuie revine pe linia 9, moment n care $a are iar valoarea 42. De ce?
Rspunsul e simplu: parametrul (variabila) $a al funciei i variabila $a din scope-ul global nu au
nimic n comun. Sunt dou variabile complet diferite.
Variabila $a din scope-ul global exist doar n scope-ul global, iar variabila $a folosit ca parametru
n interiorul funciei exist doar n interiorul funciei.
Voi ilustra asta cu un cod mai sugestiv, redenumind variabila $a din scope-ul global:
1
2
3
4
5
6
7
8
9

<?php
function increment ($a){
$a='bar ';
echo"in interior \$aeste$a\n";
}
$foo=42;
echo"$foo\n";
increment ($foo);
echo"$foo\n";

Variabila $foo se a n contextul global, n tabelul cu variabile globale. Atunci cnd apelm funcia
increment pe linia 8, ceea ce pasm funciei nu este variabila $foo, ci doar valoarea ei. Aceast metod
de a pasa parametri se numete pass by value. Acesta este motivul pentru care cele dou scripturi
funcioneaz absolut identic, dei variabilele sunt numite diferit. Aici nu este vorba despre numele
variabilelor, ci de valorile lor (uxul de date) i pe unde trece execuia (uxul de execuie).
n momentul n care uxul de execuie intr n funcie, PHP creaz un nou tabel de variabile, care,
pentru c e nou, e gol. i-ai dat seama de asta, nu? Orice variabil declarat sau folosit n aceast
funcie se pierde o dat cu ieirea uxului de execuie din funcie.
PHP vede ns c funcia accept i un parametru numit $a, i l creaz i pe acesta, ns tot n
tabelul de variabile al scope-ului local funciei increment(). Din acest motiv, logica i operaiile din
interiorul funciei sunt complet decuplate de lumea exterioar.
Datorit faptului c PHP creaz i distruge automat scope-uri, dac n interiorul unei funcii am face
lucruri precum n listingul 2.14, atunci nu am polua scope-ul global. Acele variabile variabile create ar
exista doar n interiorul funciei, i ar distruse o dat ce uxul de execuie prsete funcia.
O funcie poate accepta orici parametri. n astfel de cazuri, ei trebuie separai prin virgul unul de
altul. Exemplu:
1
2
3
4
5
6

<?php
function add($a ,$b){
return $a+$b;
}
$foo=add (42 ,43);
echo$foo;

R
U

Nu uita c introducerea de noi variabile ar trebui fcut doar atunci cnd avem de gnd s
refolosim acele variabile.

Atunci cnd creezi o funcie care returneaz valori numerice ca statusuri de eroare, creaz
constante simbolice n afara funciei pentru aceste statusuri i returneaz acele constante
simbolice n loc de numerele efective. Astfel poi schimba valorile efective returnate, ns cei
care i apeleaz funcia o vor folosi aa cum au folosit-o mereu, deoarece numele constantelor
simbolice nu se schimb.
88

Dezvoltare web cu PHP

3.1. FUNCII

n exemplul de mai sus, aa cum e el, introducerea variabilei $foo este o practic proast, era sucient
s i pasm retval-ul funciei direct lui echo:
1

echoadd (42 ,43);

in s subliniez nc o dat: retval-ul unei funcii este o valoare ca oricare alta. Este creat transparent
pentru noi de PHP, la fel cum ntr-un exemplu precum:
1
2

<?php
'a'.'b ';

din a i b rezult o valoare nou ab transparent pentru noi, n urma concatenrii.

Execuia liniar nu conine mereu toate vericrile dintr-o condiie**

Explic de ce funcia pass_is_correct este apelat n cazul urmtor


1
2
3
4
5
6
7
8
9

<?php
function pass_is_correct ( $password ){
echo'vom confrunta parola cu valoarea corecta ';
return 'foo '=== $password ;
}
$input ='bar ';
if (! empty ( $input )&& pass_is_correct ( $input )){
echo'autentificat ';
}

dar nu este apelat n cazul urmtor:


1
2
3
4
5
6
7
8
9

<?php
function pass_is_correct ( $password ){
echo'vom confrunta parola cu valoarea corecta ';
return 'foo '=== $password ;
}
$input = '';
if (! empty ( $input )&& pass_is_correct ( $input )){
echo'autentificat ';
}

Fie codul:
1
2
3
4
5
6
7
8

Fluxul de execuie i apeluri nested la funcii*

<?php
function foo($a){
return $a +1;
}
function bar($b){
return $b *42;
}
echofoo(bar(foo(foo (38))+2));

Explic pe rnd pe unde trece uxul de execuie i perechile de operaii de adunare i de nmulire care
sunt executate.
Exist o modalitate de a rupe izolarea inerent crerii de scopuri noi n interiorul funciilor: global.
Cu acest cuvnt cheie, poi lega (en. to bind) un identicator din scope-ul local de scope-ul global.
Exemplu:
89

Dezvoltare web cu PHP

1
2
3
4
5
6
7
8

3.1. FUNCII

<?php
function increment_foo (){
global $foo;
$foo ++;
}
$foo=41;
increment_foo ();
echo$foo;

n cazul nostru concret, o astfel de funcie care acceseaz i/sau modic variabile din scope-ul global
este inutil. S zicem c funcia increment_foo() ar implementa un algoritm complicat, sau nu. Nu
prea conteaz. Ideea este c o astfel de funcie este strns legat de variabila global $foo, ceea ce o face
nereutilizabil. ns tocmai acesta e scopul unei funcii: un algoritm nchis, ca o cutie neagr, care poate
parametrizat i care eventual returneaz o valoare ce poate considerat outputul acelui algoritm.

Din acest motiv, folosirea lui global este o practic proast.

Exist unele variabile predenite care sunt n mod automat globale, fr a trebui s le denim noi
ca atare. Din acest motiv aceste variabile se numesc superglobale. Printre acestea se numr i $_GET i
$_POST, pe care le-am folosit pentru preluarea inputului.
Dei sunt superglobale, deci ne sunt puse la dispoziie automat de PHP n orice scope, e el global,
e local unei funcii, acestea nu ar trebui accesate direct de funcii, ci primite ca parametru, ca orice alte
valori.
De exemplu, avem nevoie de o funcie care s ne returneze toate numerele mai mici sau egale cu 42
primite ca input. Am tentai s procedm astfel:
1
2
3
4
5
6
7
8
9
10
11

<?php
function get_all_under_42 (){
$r= array ();
foreach ( $_GET as$k=>$v){
if($v <=42){
$r[$k]=$v;
}
}
return $r;
}
var_dump ( get_all_under_42 ());

Dar ce se ntmpl dac primim datele prin POST, nu prin GET? Scriem o nou funcie pentru POST?
Inacceptabil, asta duce la duplicarea codului n mod inutil. i mai ru, dac vrem s procesm un array
oarecare n acest mod?
Mult mai bine este s crem o funcie att de generic nct s poat folosit cu orice array, e el
global, superglobal, sau local:
1
2
3
4
5
6
7
8
9
10
11

<?php
function get_all_under_42 ( $data ){
$r= array ();
foreach ( $data as$k=>$v){
if($v <=42){
$r[$k]=$v;
}
}
return $r;
}
var_dump ( get_all_under_42 ( $_GET ));

Mult mai elegant, dar mai ales, mult mai reutilizabil.


Aa cum cuvntul cheie global rupe izolarea creat automat de scope-uri, tot la fel putem rupe
90

Dezvoltare web cu PHP

3.1. FUNCII

tergerea automat a unor variabile o dat cu ieirea din scope-ul local al funciei cu un alt cuvnt cheie:
static.
Variabilele statice sunt iniializate prima oar cnd uxul de execuie le ntlnete, i apoi nu mai
dispar.
O astfel de variabil static poate folosit de exemplu pentru a salva numrul de apeluri la funcia
n care se a. Exemplu:
<?php
function foo (){
static $calls =0;
$calls ++;
return "foohasbeen called $calls time(s)";
}
echofoo () ,PHP_EOL ;
echofoo ();

1
2
3
4
5
6
7
8

Variabila static este tot o variabil local funciei. Exemplu:


<?php
function foo (){
static $calls =0;
$calls ++;
return "foowas called $calls time(s)". PHP_EOL ;
}
function bar (){
static $calls =0;
$calls ++;
return "barwas called $calls time(s)". PHP_EOL ;
}
echofoo ();
echobar ();
echofoo ();
echobar ();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

static vs. global

1. De ce nu are sens declararea unei variabile statice n scope-ul global?


2. Dincolo de faptul c PHP nu ne las din punct de vedere sintactic, de ce nu are sens declararea
unei variabile statice i globale n acelai timp, n interiorul unei funcii?

3.1.2 Cnd s introducem funcii noi


n acest moment tim ce constructe ne pune PHP la dispoziie i ce posibiliti avem. Acum vom
face un pas napoi i ne vom gndi: cnd este necesar s introducem funcii noi, i cnd nu?
Pentru a nelege asta, trebuie s nelegem ce nseamn a programa.5
Atunci cnd vrem s programm, o facem pentru c suntem pui n faa unei probleme. eful i-a
spus c trebuie s faci o aplicaie care s fac X, Y, Z, i tu trebuie s o faci. Este problema ta cum
rezolvi aceast problem, ns totul pleac de la ea.
O dat pus n faa unei probleme, este treaba programatorului s o rezolve. Orice programator va
rezolva problema la un moment dat, ns un programator bun nu numai c va rezolva problema, dar o
va rezolva i n aa fel nct s poat reutiliza funcionalitile implementate i n proiectele viitoare.
5

M refer strict la actul de creaie, nu la documentare, testare, sau ali pai care vor introdui n capitole viitoare

91

Dezvoltare web cu PHP

3.1. FUNCII

De exemplu, foarte multe aplicaii web au funcionalitatea de login/logout. Un programator naiv va


mzgli la grmad ceva, i va rezolva problema, poate implementaia sa va foarte rapid, iar eful va
fericit c a rezolvat-o att de repede.
Dar acea implementaie nu va reutilizabil n aplicaiile viitoare, programatorul va pierde la ecare
aplicaie acelai timp constant, pentru c de obicei ecare aplicaie are unele cerine specice, unice, n
ciuda faptului c funcionalitatea este n mare aceeai.
Pe termen lung, programatorul naiv va pierde cumulativ mai mult timp dect un programator care
investete iniial mai mult timp i energie, dar care recupereaz din acest timp cu ecare nou proiect.
Programatorul bun va rupe problema mare n subprobleme mai mici. Aceste subprobleme pot
constituite la rndul lor din alte subprobleme.
Vom formaliza acest scenariu, pentru o ilustrare mai clar. Avem o problem ctiv P. Ea const n
rezolvarea problemelor P1 , P2 i P3 . Aceste subprobleme sunt mai puin complexe dect problema P. P1
la rndul ei poate decompus n alte dou subprobleme, P1 1 i P1 2 .
Trecnd la analiza subproblemei P2 , programatorul realizeaz c datele pe care aceasta opereaz sunt
foarte similare cu datele pe care le-ar returna P12 , deci practic, fcnd abstracie de cteva detalii de
implementaie, P2 = P12 .
Folosind deci algoritmii din P1 2 , programatorul rezolv o alt subproblem a lui P , i anume P2 .

Aceast mprire (en. breaking down) a problemei se numete modularizare.

Sun simplu, dar n realitate nu este deloc aa. Programatorul trebuie s analizeze foarte bine
problemele, i s le descompun n subprobleme reutilizabile. Nici mcar la nivel academic nu exist
strategii clare de modularizare a codului care s funcioneze mereu.
Ne vom uita la o problem simpl, care este complex destul pentru a conine subprobleme
reutilizabile, i pe care o putem rezolva n PHP.
Se dau trei numere, a, b, c, pe care trebuie s le sortm cresctor. Altfel spus, la nal armaia
a b c trebuie s e adevrat. Numerele pot avea orice valori iniiale. Cum procedm?
Dac nu ai nici o idee, atunci hai s abordm la modul naiv problema. Din problem, tim cu
certitudine c exist n total ase posibile ordonri: abc6 , bca, cab, bac, cba, acb. Fiecare ordonare este
de fapt o permutaie, i deoarece conine trei elemente se mai numete i triplet de numere.
Un alt lucru cert este c nu putem compara dect dou numere n acelai timp, o expresie de genul
a b c neind posibil n PHP, ar trebui s unim conjunctiv a b i b c.
Dac rescriem cei ase triplei matematic, n perechi conjunctive, observm c toate comparaiile de
genul a b apar de dou ori. Deci de ce s vericm de dou ori aceeai condiie, cnd putem verica
o singur dat? Este un principiu fundamental n programare: ncearc s reutilizezi ct mai mult din
algoritmii implementai.
Astfel, lund de exemplu perechea a b, avem dou categorii de triplei:
cei ce ndeplinesc aceast condiie: abc, cab, acb
cei ce nu ndeplinesc condiia: bca, bac, cba
Practic am simplicat astfel problema, pe ramura TRUE a comparaiei tratm trei cazuri, pe ramura
FALSE celelalte trei cazuri. Dar asta nu e tot. Suntem ambiioi, i vrem s reectm i mai mult asupra
problemei.
Care este esena faptului c am stabilit relaia dintre cele dou numere a i b, i ce legtur are asta
cu c?
n esen, relaia lui c fa de perechea a, b poate de trei tipuri:
ori se a naintea perechii, deci avem de-a face cu tripletul cab pe ramura TRUE, sau cu tripletul
cba pe ramura FALSE
6

prescurtare pentru a b c

92

Dezvoltare web cu PHP

3.1. FUNCII

ori se a exact ntre a i b, deci avem de-a face cu tripletul acb pe ramura TRUE sau cu tripletul
bca pe ramura FALSE
ori se a dup aceast pereche, deci c este mai mare att dect a, ct i dect b, deci avem de-a
face cu tripletul abc pe ramura TRUE sau cu tripletul bac pe ramura FALSE
Asigur-te c toate gndurile expuse de mine pn aici i s-au aezat bine n creier.
Detandu-ne puin de problem, realizm c att cazul TRUE, ct i cazul FALSE al comparaiei
a b reutilizeaz aceeai subproblem, doar c a, b sunt ordonate diferit, ori ca ab, ori ca ba. Perechea
a, b este deja ordonat, deci nu ne rmne dect s inserm c-ul la poziia corect. Perechea b, a nu
trebuie dect inversat, astfel nct b s primeasc valoarea lui a, iar a s primeasc valoarea lui b, deci
a i b s e ordonate unul relativ la altul.
Cum ar arta asta algoritmic? Hai s o lum treptat:
1
2
3
4

dacaa <=b
// ceva
altfel
a,b=b,a

Exact! Dup execuia liniei 4, dup ce am inversat cele dou valori, problema de pe ramura altfel
devine problema de pe ramura daca. Nu avem dect s inventm o funcie care accept o pereche de
numere ordonate a, b i nc un numr c, funcie care insereaz c la poziia corect, nainte, dup, sau
ntre a, b. Aceast funcie va putea apelat att pe ramura TRUE, ct i pe ramura FALSE a uxului
de execuie.
Un singur lucru specic PHP nu l tim: cum s inversm dou valori. Pentru asta putem folosi o
variabil intermediar, de exemplu $t (care st n mod intuitiv pentru temporar):
1
2
3
4

<?php
$t=$a;
$a=$b;
$b=$t;

O alt metod este s folosim un construct PHP: list(). Cu el putem despacheta un array n
componentele sale, deoarece l putem folosi i de partea stng a atribuirii:
1
2

<?php
list($b ,$a)= array ($a ,$b);

Exact, datorit asociativitii de dreapta a atribuirii, mai nti crem un array, apoi l despachetm cu
list(). ns l despachetm invers! Astfel, n urm atribuirii, valoarea lui $a aterizeaz n $b i vice-versa.
Deci codul nostru va arta aa:
1
2
3
4
5
6
7
8
9
10
11
12

<?php
$a=(int) $_GET ['a '];
$b=(int) $_GET ['b '];
$c=(int) $_GET ['c '];
if($a <=$b){
list($a ,$b ,$c)= insert_at_right_pos ($a ,$b ,$c);
}
else{
list($a ,$b)= array ($b ,$a);
list($a ,$b ,$c)= insert_at_right_pos ($a ,$b ,$c);
}
echo"$a <=$b <=$c ";

93

Dezvoltare web cu PHP

3.1. FUNCII

Insert at the right position***


Partea I

Un singur lucru mai lipsete n listingul anterior: implemetarea funciei insert_at_right_pos().


Implementeaz-o.

Partea II
Completeaz urmtorul cod cu o implementaie corect a funciei sort_triplet_desc:
<?php
$a=(int) $_GET ['a '];
$b=(int) $_GET ['b '];
$c=(int) $_GET ['c '];

1
2
3
4
5

list($a ,$b ,$c)= sort_triplet_desc ($a ,$b ,$c);

6
7

echo"$a >=$b >=$c ";

ntr-adevr am depus mult mai mult efort n analiza problemei noastre, dar nu numai c am refolosit
cod n mod destul de inteligent n cadrul aceleiai probleme prin implementaia de funcii, dar aceste
funcii vor putea refolosite fr prea multe eforturi n toate proiectele viitoare.
Pentru a mpri o problem n subprobleme, nu trebuie dect s analizezi cu grij problema, inputul,
i ce se vrea ca output, i s identici funcionaliti comune.
Cum trebuie s mpari o problem nu poate nvat din cri, ci doar prin practic, avnd pe
cineva lng tine care s-i atrag atenia atunci cnd ai greit, i care s-i dea sfaturi de mbuntire
a modularizrii codului tu. Pentru acest lucru, comunitatea phpro7 i st la dispoziie, unde persoane
cu experien te vor tutela.
O regul de baz pe care oricine o poate urma, este s te desprinzi de output. Una este
procesarea cu un algoritm a datelor fundamentale de la baza aplicaiei, alta este generarea de
output.
Toate funciile, poate cu excepia a ctorva, ar trebui s opereze pe date i att. Gndete-te
c depui efort n rezolvarea unei probleme sau subprobleme, i vrei ca implementaia s e ct
mai reutilizabil. Ce se ntmpl dac nu vrei s aezi un rezultat n browser, ci s trimii
rezultatul prin e-mail, sau s generezi documente n alte formate precum PDF n loc de HTML?
n astfel de cazuri va trebui s modici funciile. Sau altfel spus: n astfel de cazuri spunem c
nu i-ai fcut funciile reutilizabile.
Nu uita c, atunci cnd creezi funcii, acestea trebuie s e utile i pentru cazuri pentru care
nu au fost gndite de fapt. Pentru asta, funciile tale trebuie s e n primul rnd izolate de
orice ine de mediul sau de circumstanele n care acestea sunt apelate.

Static is almost bad, global is evil


n concordan cu paragraful anterior, static poate periculos dac interfereaz cu uxul de execuie,
iar global este periculos deoarece rupe izolarea pe care ar trebui s-o aib implementaia ecrei funcii.
Ca regul general, nu uita c o funcie trebuie s returneze aceeai valoare pentru aceleai valori
primite ca parametri, orice s-ar ntmpla ntre dou apeluri la acea funcie. Exemplu:
<?php
function foo($nr){
return ++ $nr;
}

1
2
3
4
7

https://github.com/yet-another-project/phpro-book

94

Dezvoltare web cu PHP

5
6
7
8

3.1. FUNCII

$a=41;
echofoo($a);
$b=++ $a;
echofoo($b);

Aceast funcie este bine izolat de lumea exterioar, deoarece se manifest consistent pentru toate
inputurile, indiferent de cum arat uxul de execuie i de date n apelant.

Fluxul de execuie, i implicit i de date, dintr-o funcie bine scris poate anticipat mereu.

O practic greit este s modici valorile variabilelor globale sau superglobale n interiorul
funciilor. Astfel de modicri, i n general orice fel de bizuire pe variabilele globale, trebuie
evitate cu orice pre.
Opernd pe o variabil global sau superglobal, nu poi ti ce alte pri ale aplicaiei vor
inuenate.
Chiar dac tii n acest moment c nu exist riscuri, nu uita c vei uita cum i-ai construit
aplicaia i ce interdependene de funcionalitate ai creat. Dar chiar dac ai uitat, vei pus n
situaia de a personaliza anumite pri din aplicaie. Este foarte probabil s nu mai i contient
de aceste interdependene n momentul n care vei personaliza acele lucruri.

3.1.3 Funcii variabile


Putem salva identicatori de funcii n variabile, ca stringuri, i apela acele funcii prin intermediul
variabilelor. Exemplu:
1
2
3
4
5
6

<?php
function foo($a){
return ++ $a;
}
$do_it ='foo ';
$test =41;

7
8

echo $do_it ( $test );

Nu este nimic deosebit sau dicil n ce se ntmpl.


Funciile variabile i pot face codul greu de neles i de mentenat. Evit folosirea lor acolo
unde nu rezolv mai elegant o problem sau nu aduc nimic n plus.

Funciile variabile sunt strns legate de ceea ce numim callbacks. Un callback este o funcie pe care
i-o pasm ca parametru unei alte funcii. Acea funcie va folosi callback-ul pasat dup nevoi.
O astfel de funcie este array_walk. Ea apeleaz callback-ul pentru ecare pereche key => value a
array-ului pe care i-l pasm ca parametru.
Semntura funciei este
bool array_walk(array &$a, callback $cb [, mixed $userdata])
Un exemplu:
1
2
3
4
5
6
7
8
9
10

<?php
$foo= array (
'foo '=>'bar ',
42=>'theanswer ',
'thequestion '=>NULL
);
function display_array ($value ,$key){
echo"$key=>$value <br/>", PHP_EOL ;
}
array_walk ($foo ,' display_array ');

95

Dezvoltare web cu PHP

3.1. FUNCII

Exact, se numete walk deoarece se plimb prin array. Corect spunem c array_walk() itereaz
array-ul cu un callback.

Callbacks

Implementeaz o funcie cu urmtoarea semntur:


array call_and_filter(array $array, callback $cb)
unde callback-ul trebuie s aib semntura
bool my_cb(int $key)
care apeleaz callback-ul pentru toate elementele array-ului i dac callback-ul returneaz TRUE, atunci
adaug valoarea aat la $key ntr-un array $r.
Callback-ul nsui my_cb() trebuie s returneze TRUE pentru toate numerele pozitive mai mici sau
egale cu 42.
Dup ce a terminat de iterat array-ul primit ca parametru, call_and_filter() trebuie s returneze
array-ul rezultat $r.

3.1.4 Closures
Closures, sau funcii anonime, pot , la fel ca i funciile variabile, folosite ca callbacks, ns pot avea
multe alte ntrebuinri.
Se numesc funcii anonime deoarece nu au un nume, doar o implementaie. Deoarece vrem s i folosim
o astfel de funcie, trebuie s o salvm undeva, i ce altceva s-ar potrivi mai bine dect o variabil?
De notat este c a salva nseamn n termeni PHP a atribui, deci trebuie s e respectat sintaxa
atribuirii:
$var = <expr>;
Pentru a atribui o funcie anonim unei variabile, pur i simplu atribuim implementaia funciei variabilei:
1
2
3
4

<?php
$foo= function (){
return 42;
};

5
6

echo$foo ();

Apelul efectiv este la fel ca n cazul funciilor variabile, cu excepia c n cazul lor variabila avea ca
valoare un string, ns acum are ca valoare:
1

var_dump ($foo);

Exact! Un obiect de tip Closure. Vom reveni asupra programrii orientat pe obiecte ntr-un capitol
viitor.
Numele de closure ne spune c ele pot de fapt mult mai mult. Un closure poate acapara i variabile
din scope-ul n care se a.
De exemplu, acest closure folosete variabila $a din scope-ul global, deoarece closure-ul nsui este
declarat n acest scope:
1
2
3
4
5

<?php
$a=4;
$multiply_by_a = function ($b)use($a){
return $a*$b;
};

6
7

echo $multiply_by_a (3);

96

Dezvoltare web cu PHP

3.1. FUNCII

Clauza use poate accepta, la fel ca i funcia, o list de parametri multipli separai prin virgul. Aceast
list conine lista variabilelor a cror valoare trebuie preluat din scope-ul printe.
Cu adevrat utile devin closures cnd sunt create n interiorul altor funcii care creaz i returneaz
aceste closures, n funcie de parametrii primii.
Exemplu:
1
2
3
4
5
6

<?php
function multiply_by ( $multiplier ){
return function ($a)use( $multiplier ){
return $a* $multiplier ;
};
}

7
8
9

$double = multiply_by (2);


$triple = multiply_by (3);

10
11

echo $triple ( $double (1));

La ecare apel, multiply_by() ne va returna un nou closure de tipul necesar.

Aarea unui array bidimensional

La sfritul capitolului trecut probabil ai creat un script care, pornind de la un array asociativ, genera
un tabel XHTML.
Scrie o funcie
string array_table(array $data)
care genereaz codul XHTML cu reprezentarea acelor date ntr-un tabel i care returneaz acest cod
apelantului.

3.1.5 Default values


Parametrii funciilor pot avea valori standard (en. default). Aceste valori trebuie s e valori constante
precum TRUE, FALSE, NULL, stringuri sau numere, iar parametrii respectivi iau acele valori doar dac
apelantul nu specic o valoare.
Pentru a atribui o valoare default unui parametru, folosim sintaxa deja cunoscut:
$param = <value>
De exemplu, o funcie care l salut pe utilizator n funcie de limb poate arta aa:
1
2
3
4
5
6
7
8
9
10

<?php
function greet ($username , $language ='en '){
$greetings = array (
'en '=>'Hello ',
'de '=>'Hallo ',
'ro '=>'Salut ',
'fr '=>'Salut ',
);
return $greetings [ $language ]. $username ;
}

11
12
13

echogreet ('Flavius ','de ');


echogreet ('Xulescu ');

Deoarece parametrii cu valori default pot specicai de apelant sau nu, aceti parametri se mai numesc
i opionali.
97

Dezvoltare web cu PHP

3.2. DEBUGGING

Parametrii cu valori default nu pot sta dect la sfrit, iar dup ei nu mai pot aprea parametri
obligatorii. O astfel de funcie nu este posibil:
void foo($a=42,$bar)
$bar ar trebui s e primul parametru, i dup el s urmeze parametrii opionali.

Debugging
Deseori te vei lovi de probleme i va trebui s le izolezi cauza pentru a le putea repara. Chiar dac
ceea ce vrei nu este s rezolvi tu nsui problema, ci s apelezi la ajutorul altcuiva, tot va trebui s o
izolezi.
De ce? Motivul e simplu: nimeni nu te poate ajuta fr a avea o idee concret despre ce nu
funcioneaz aa cum te atepi s funcioneze. De aceea

Nu spune niciodat Nu merge. Faptul c nu merge e evident, din moment ce ai o problem. n


programare trebuie s spui exact ce nu merge, i s depui efort pentru a izola exact cauza.

n primul rnd, asigur-te c ai instalat i congurat PHP pentru dezvoltare, aa cum eti instrucionat
n capitolul 1. Acesta nu este un pas opional: este foarte probabil ca PHP s i spun unde este greeala,
dar tu s nu o vezi pentru c nu ai congurat PHP corespunztor.
n al doilea rnd, apache scrie mesajele de eroare ntlnite n ierul error_log din subdirectorul
logs. Asigur-te c citeti i nelegi ce scrie acolo.
Pentru depanarea (en. debugging) efectiv, folosete var_dump() pentru a inspecta valorile
variabilelor n puncte cheie din execuie - poate c unele variabile nu au valorile pe care te atepi
s le aib!? Asigur-te nainte de toate.
Adiional, poi vedea pe unde trece uxul de execuie folosind constantele magice __FILE__, __LINE__
sau __FUNCTION__:
1

echo'fluxul de executie trece prin', __FUNCTION__ , '(',__LINE__ , ')', PHP_EOL ;

Dup ce ai izolat problema, scrie un cod minimal de maxim 20-50 LOCs, care s o reproduc. Acest
cod se numete POC (en. Proof of Concept). Dac nu reueti s rezolvi problema, apeleaz la ajutorul
unui tutore phpro, folosind acest POC.
Crearea unui POC nu este un efort inutil. Nu de puine ori izolarea problemei i reproducerea sa cu
ajutorul unui POC te va duce direct ctre rezolvarea sa, i astfel nu vei mai avea nevoie de susinerea
cuiva.
Folosirea var_dump() i a constantelor magice nu este cel mai profesionalist mod de a depana o
aplicaie - n capitolul urmtor vom vedea i cum se face corect. Tehnica prezentat aici este doar o
metod improvizat, sucient pentru a-i putea analiza i rezolva problemele de unul singur.

Folosirea manualului
Pn acum am fcut cunotin cu posibilitile limbajului PHP. ns pentru a util, el trebuie i s
pun la dispoziie funcionaliti deja scrise de ali programatori. Aceste funcionaliti sunt de obicei
mpachetate n funcii. De exemplu, am folosit deja funcii ca var_dump(), fr a ne ntreba prea multe
despre ea.
Dup cum tii, toate funciile au o implementaie. ns noi nu am implementat nicieri funcia
var_dump(). Unde este ea implementat? Rspunsul: ntr-o extensie PHP.
PHP n sinea lui nu tie s fac mult mai multe lucruri dect am vzut deja. Pentru a-l face cu
adevrat util, creatorii limbajului l distribuie mpreun cu extensii, numite i module.
Pentru a vedea lista modulelor ncarcate n PHP, lanseaz n CLI php cu parametrul m:
98

Dezvoltare web cu PHP

3.3. FOLOSIREA MANUALULUI

php -m Unele module sunt att de aproape de inima interpreterului PHP, nct nici nu pot dezactivate.8
Din acest motiv, acestea par a face parte din PHP. n realitate, limbajul PHP este doar scheletul, restul
funcionalitilor ind puse la dispoziie de aceste extensii.
De notat este c PHP include nu numai extensii scrise de inventatorii limbajului PHP, ci mai ales
legturi (en. bindings) ctre bibliotecile altor programe. De exemplu, GD este o bibliotec folosit de
programatorii C pentru a desena programatic imagini. PHP doar pune la dispoziie o interfa prin care
aplicaiile tale scrise n PHP pot apela funciile specice libgd.9 Asta permite programatorilor familiari
deja cu GD s scrie aplicaii n PHP fr a depune eforturi prea mari, deoarece conceptele, i chiar i
numele funciilor, sunt foarte similare cu cele puse la dispoziie de libgd direct.
n acelai timp, programatorii PHP cu cunotine C pot rescrie foarte uor pri din aplicaiile lor
care iniial erau scrise n PHP, n C, deoarece ei cunosc deja numele funciilor, parametrii, dar mai ales
conceptele din spate specice bibliotecii (en. library) GD.

Cnd nvei s lucrezi cu funciile puse la dispoziie de un modul care pune la dispoziie o
funcionalitate pentru o anumit clas de probleme, nva i nelege n primul rnd conceptele
din spate.
Astfel vei putea trece de la PHP la alt tehnologie i totui i vei putea folosi cunotinele,
indiferent de limbajul de programare folosit.

3.3.1 Site-ul ocial php.net


Intr pe site-ul ocial al limbajului PHP: http://php.net/. Urmeaz link-ul din dreapta sus my
php.net, i seteaz-i limba ca n gura 3.1.

Figura 3.1: Limba php.net


Seteaz-i i urmtoarele preferine:
URL search fallback Function list search
Mirror site redirection alege un mirror apropiat de locaia ta geograc
Restul setrilor rmn la atitudinea ta.
Cu Firefox, mai poi aduga php.net i ca motor de cutare, ca n gura 3.2.
Introdu var_dump n cmpul de cutare, i vei condus ctre pagina din manual a funciei. Acolo
poi vedea n ordine
versiunile PHP n care exist funcia
o descriere scurt a funciei
semntura funciei i o descriere pe larg
8
9

De exemplu extensia standard


lib este prescurtarea de la library.

99

Dezvoltare web cu PHP

3.3. FOLOSIREA MANUALULUI

Figura 3.2: Cutare n manualul PHP cu Firefox


eventuale avertizri
lista parametrilor i semnicaia lor
valoarea returnat
exemple de utilizare
funcii nrudite
comentarii ale altor utilizatori
Sunt o grmad de informaii. Practic, manualul PHP conine toate informaiile de care ai nevoie. Din
acest motiv cartea de fa nu ncearc s duplice explicaiile pe care le poi gsi n manual, ci doar s
te cluzeasc. n plus, comentariile celorlali sunt extrem de utile. Foarte rar te vei aa ntr-o situaie
unic n care nu s-a mai aat nimeni altcineva i comentariile acelea nu i vor de folos. E recomandat
s le citeti i pe ele.

U
R

Cartea nu va explica toate funciile folosite n listinguri. Cnd ntlneti o funcie nou, trebuie
s te documentezi din manual.
Ceea ce i se va explica n carte sunt conceptele generale i termenii, astfel nct s te poi
descurca singur.

3.3.2 Studiu de caz: funcii variadice


Dup cum observi n manual, funcia var_dump() are de fapt semntura
void var_dump (mixed $expression [, mixed $expression [, $... ]])
nseamn c funcia accept un numr variabil de parametri, ns trebuie s e cel puin unul. Astfel
de funcii se numesc funcii variadice (en. variadic).

Creaz o funcie variadic


Partea I

Caut n manual funcia func_num_args() i toate funciile nrudite cu ea pentru a crea o funcie
variadic care returneaz produsul parametrilor pasai.

Partea II
Scrie o nou versiune a funciei care are semntura
100

Dezvoltare web cu PHP

3.3. FOLOSIREA MANUALULUI

int array_product(...)
i care returneaz produsul numerelor salvate n array.

3.3.3 Categoriile de extensii disponibile


Pe pagina ocial ind, dac navighezi ctre Documentation View online English, vei ajunge
la indexul manualului, la pagina sa de start.
Capitolele mari prezentate sunt lucruri precum Getting Started care conine i un tutorial, Language
Reference, pe care l-ai citit ca parte dintr-un exerciiu din capitolul trecut, Security care conine sfaturi
de securitate, i asupra crora vom reveni i noi n acest capitol, Features i prezint unele capaciti ale
lui PHP folosite n mod tipic de aplicaii, PHP at the Core: A Hackers Guide to the Zend Engine i
prezint inima interpreterului PHP, i alte cteva capitole.
Deocamdat vrem s ne facem o imagine de ansamblu a funciilor puse la dispoziie, din capitolul
Function Reference.
Aecting PHPs Behaviour sunt extensii care afecteaz modul fundamental de funcionare al lui PHP.
De astfel de funcii nu vei avea nevoie dect cnd ajungi la nivelul avansat. Unele dintre cele mai des
folosite extensii din aceast categorie sunt aa numitele opcode cachers, asupra crora vom reveni ntr-un
capitol viitor.
Extensiile pentru Audio Formats Manipulation pun la dispoziie funcii pentru formate audio de iere
i metadate salvate n astfel de iere.
Authentication Services sunt pentru servicii de autenticare, utile n situaii destul de complexe n
care trebuie s integrezi autenticarea utilizatorilor n alte servicii deja existente, sau s faci autenticarea
folosind servicii centralizate cu care i alte aplicaii pot comunica.
Date and Time Related Extensions conin funcii pentru lucrul cu date i timp, diferena dintre dou
date, convertirea de input care reprezint date sau timp n formate numerice uor de neles de ctre
calculatoare10 sau fuse orare.
Compression and Archive Extensions se ocup de formate de iere precum zip sau phar,11 un format
de arhivare propriu PHP care-i permite s incluzi aplicaii ntregi dintr-un singur foc, chiar dac acestea
conin cteva mii de iere cu cod surs.
Credit Card Processing sunt pentru procesarea crilor de credit.
Cryptography Extensions sunt utile atunci cnd vrei s criptezi informaii importante, precum
numerele de conturi pe care le procesezi cu funciile de procesare ale crilor de credit.
Database Extensions pun la dispoziie extensii pentru comunicarea cu baze de date. MySQL este
unul dintre cele mai folosite sisteme de management al bazelor de date n aplicaiile PHP, ns exist o
grmad de alte sisteme pentru organizarea structurat a informaiilor.
File System Related Extensions se ocup cu lucrul cu iere i directoare, citirea sau scrierea din/n
iere, listarea ierelor dintr-un director, informaii despre iere precum drepturile de acces sau posesorii
acestora.
Human Language and Character Encoding Support sunt printre altele pentru internaionalizarea
aplicaiilor. Dac vrei s faci o aplicaie cu interfaa n mai multe limbi, atunci trebuie s apelezi la
funcionalitile puse la dispoziie de aceste extensii.
Image Processing and Generation sunt pentru prelucrarea i generarea programatic a imaginilor.
Mail Related Extensions sunt pentru lucrul cu diferite protocoluri sau formate de e-mail.
Mathematical Extensions pun la dispoziie funcii matematice.
HTML este un limbaj bazat pe text. Non-Text MIME Output se ocup cu generarea de documente
sau resurse n alte formate pe lng text precum animaii ash sau documente PDF.
10
11

timestamps
php archive

101

Dezvoltare web cu PHP

3.3. FOLOSIREA MANUALULUI

Funciile din extensiile de Process Control Extensions i permit s lansezi n execuie alte programe
cu interfa CLI i s comunici cu acestea e citind i scriind din/n outputul/inputul acelor procese, e
prin alte mecanisme precum IPC (en. inter-process communication).
Other Basic Extensions sunt extensii care pun la dispoziie diferite funcionaliti de baz. Cele mai
des ntlnite i folosite sunt cele din extensia URLs i din extensia Miscellaneous Functions.
Other Services conine o mulime de extensii. Una dintre cele mai comune este sockets. Cu ea poi
deschide conexiuni programatic, aa cum ai fcut cu telnet, i transfera date (n orice protocol, nu numai
HTTP). Alt extensie folosit des este cURL, cu care poi deschide conexiuni HTTP, fr a nevoit s
creezi manual cererile HTTP, aa cum ai face-o cu sockets.
Search Engine Extensions sunt extensii care te las s comunici cu ali daemoni care au menirea de
a indexa iere i de a te lsa s caui dup cuvinte cheie de exemplu. Majoritatea aplicaiilor comune
scrise n PHP nu folosesc aceste servicii deoarece pentru aplicaii mici necesit prea multe resurse. Ele
salveaz datele n baze de date, de obicei MySQL, i caut manual. Aceste extensii pentru search engine
sunt totui foarte utile cnd vrei s faci ceva extensibil, fr a pune presiune pe o baz de date. Ele
reprezint de fapt moduri corecte de a implementa funcionalitatea de cutare pe un site.
Server Specic Extensions pun la dispoziie funcii specice SAPI-ului folosit. Dac ai instalat i
congurat mediul de programare ca n capitolul 1, atunci foloseti SAPI-ul Apache.
Session Extensions pun la dispoziie funcionalitatea numit sesiuni. Sesiunile permit aplicaiilor web
s in minte utilizatorii i date asociate cu acetia. Mulumit sesiunilor este posibil autenticarea
utilizatorilor.
Categoria Text Processing conine extensii pentru lucrul cu text, cu stringuri. Cele mai folosite extensii
din aceast categorie sunt Strings pentru operaii cu stringuri precum cutare, stabilirea lungimii, .a.m.d.
i PCRE (en. perl-compatible regular expressions). PCRE i permite s verici dac un string potrivete
o regul12 i eventual s i extragi anumite secvene din acel string.
PCRE este puternic, dar consum i multe resurse, deci este recomandat s foloseti funciile simple din
extensia Strings atunci cnd e posibil.
Variable and Type Related Extensions pun la dispoziie funcii pentru lucrul cu tipurile de date
fundamentale din PHP (n afar de stringuri, care sunt tratate de extensiile prezentate anterior), printre
care array-uri, funcii i variabile. Atunci cnd ai cutat informaii despre funcia func_num_args() i
funciile nrudite cu ea, te-ai micat prin extensia Function Handling.
Extensiile din categoria Web Services sunt folosite pentru a crea i folosi servicii web. Atunci cnd
aplicaia ta pune la dispoziie un serviciu web, aceasta poate contactat de alte aplicaii i informaiile
pot procesate programatic mult mai uor. Acelai lucru l poi face i tu cu alte aplicaii care i
ofer funcionalitile i ca servicii web. De exemplu, reelele sociale precum Facebook13 sau Twitter14
pun la dispoziie astfel de servicii. Asta le permite altor programatori s creeze programe care posteaz
tweet-uri pe twitter sau jocuri pe care le poi juca mpreun cu prietenii ti pe facebook, aplicaii care
nu au legtur direct cu rmele originale precum twitter sau facebook n cazul nostru.
Windows Only Extensions pun la dispoziie funcionaliti specice Microsoft Windows. Acestea nu
vor funciona dect dac daemonul cu PHP integrat n el ruleaz pe windows. Este recomandat s nu
foloseti astfel de funcii dect n cazul n care tii sigur c aplicaia ta va rula ntr-un mediu controlat,
pe windows, deoarece majoritatea serverelor ruleaz pe o form sau alta de *NIX15 , nu Windows.
XML Manipulation pune la dispoziie funcionalitate pentru lucrul cu iere n formatul XML. XML
este un format care-i permite s structurezi informaii arborescente. Din punct de vedere sintactic este
similar cu HTML, iar combinaia dintre HTML i XML a dat natere limbajului XHTML. n contrast
cu (X)HTML ns, XML nu are taguri predenite. Programatorii i inventeaz propriile formate de
date i le dau o semnicaie.
Acestea au fost categoriile de extensii disponibile n PHP. Unele dintre ele vin la pachet cu PHP, altele
se a n ceea ce numim PECL (en. PHP Extension Community Library) i trebuie instalate separat.
12

Aa cum ai inventat o regul pentru sintaxa limbajului HTML n capitolul 2


http://facebook.com/
14
http://twitter.com/
15
GNU/Linux, *BSD, SunOS, etc
13

102

Dezvoltare web cu PHP

3.3. FOLOSIREA MANUALULUI

Nu uita c dei fac parte din aceeai categorie, dou extensii nu pot comunica una cu alta. De exemplu,
dac ai stabilit o conexiune cu o baz de date MySQL, atunci nu poi pasa aceast conexiune unei funcii
care lucreaz cu baze de date PostgreSQL. Cele dou extensii sunt complet diferite i independente.
Categorisirea extensiilor este doar modul de organizare a informaiilor n manualul PHP, pentru o navigare
mai uoar.

3.3.4 Extensii de baz


n categoria Variable and Type Related Extensions este o extensie cu funcii pentru lucrul cu array-uri.
Dac urmezi link-ul Array Functions vei vedea indexul tuturor funciilor pentru array-uri alturi de o
descriere scurt a ecreia.

nelege manualul

Alege cinci funcii de lucru cu array-uri i explic n cuvinte ce face ecare, apoi creaz unul sau mai
multe coduri surs care s le demonstreze utilitatea.

Exploreaz manualul***

n acest moment ai o privire destul de robust a limbajului, dar nu tii funciile care-i sunt puse la
dispoziie. Totui, mulumit explicaiilor de pn acum, eti capabil s nelegi manualul.
Rezerv-i 40-80 de ore (1-2 sptmni de lucru) pentru a explora urmtoarele extensii:
Array, Function Handling, Variable Handling din categoria Variable and Type Related Extensions
Strings din categoria Text Processing
Miscellaneous Functions din categoria Other Basic Extensions
Scrie scripturi de la simple la complexe care se folosesc de aceste funcii. Documenteaz-i scripturile cu
comentarii. La ecare script scrie i ce-i trece prin minte, ce observaii ai fcut, ce legturi sau analogii
ai fcut.
Nu uita s separi business logic de view logic i s transmii date ce rezult n urma procesrii
formularelor (business logic) ctre view logic folosind variabile intermediare.
Posteaz ecare cod surs pe phpro pentru a te verica pe parcursul celor 1-2 sptmni, nc din
momentul n care ai scris ceva nou.16 n total ar trebui s ai cteva zeci bune de scripturi, cu pn la
1000 de LOCs sau chiar mai mult.
La ecare exerciiu explic modul de funcionare n ceva asemntor cu limbaj pseudocod, dar fr a
folosi identicatori de variabile sau a reecta exact structura codului. Explic n schimb motivaiile de a
proceda ntr-un anumit fel.
Creaz un jurnal al tuturor funciilor despre care te-ai documentat singur din manual, cu semntura
funciei i o explicaie scurt despre ce face17 .
Dup aceste 1-2 sptmni nu i va mai sta nimic n calea crerii de site-uri destul de complexe
cu cteva mici excepii pe care le vom aborda n cele ce urmeaz.
16
17

Nu toate scripturile deodat


Explicaii scurte se pot gsi pe indexul funciilor din manualul PHP.

103

Dezvoltare web cu PHP

3.4. STRUCTURI DE DATE

Structuri de date
Array-urile sunt att de versatile nct pot folosite pentru a construi structuri de date mai
complicate, ecare cu avantajele i dezavantajele sale.

3.4.1 Stack i queue


Un stack este un array n care elementele sunt adugate la sfrit, i preluate tot de la sfrit. Operaia
de adugare a unui element pe stack se numete push, iar cea de scoatere se numete pop.
Un stack poate reprezentat vizual ca n gura 3.3.

pop

Figura 3.3: Operaiile cu un stack


Deoarece ultimul element adugat este primul care este ndeprtat din stack, spunem c un stack este
o structur de date de tip LIFO (en. last in, rst out).
Operaia push i este cunoscut deja prin intermediul operatorului [] pe care l-ai ntlnit n listingul
2.5. Exist i o funcie absolut echivalent n funcionalitate cu acesta: array_push().
Similar cu LIFO, exist i FIFO (en. rst in, rst out), numit i queue. Operaiile se numesc shift i
unshift, iar grac ne putem imagina o astfel de structur de date ca n gura 3.4.

shift

unshift

Figura 3.4: Operaiile cu un queue


Primul element pus n queue este primul element care va ndeprtat din queue.
Pentru aceste dou operaii exist dou funcii numite destul de intuitiv array_shift() i
array_unshift().

104

Dezvoltare web cu PHP

3.4. STRUCTURI DE DATE

Experimenteaz cu stack i queue

Scrie un script complet n care experimentezi cu aceste structuri de date. Nu uita c poi trata acelai
array alternativ, cnd ca stack, cnd ca queue.

3.4.2 Structuri de date recursive


n exerciiul 2.1 Sintaxa HTML ai fcut cunotin cu recursivitatea. n PHP poi procesa structuri
de date recursive folosind funcii recursive. De exemplu, un document HTML este o structur de date
recursiv deoarece nodurile din document18 pot avea n interiorul lor alte noduri. Din acest motiv spunem
c structurile de date recursive sunt i izomorce.
n capitolul trecut ai vzut cum poi construi array-uri n-dimensionale, unde n era bine determinat.
Un array recursiv este constituit, la fel ca i un array n-dimensional, din alte array-uri. Diferena este
c n nu este determinat. Trebuie s parcurgem recursiv array-ul pentru a procesa ecare element.
Vom lua ca exemplu un array recursiv:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<?php
$arbore = array (
'hello ',
'foo ',
'world '=> array (
'how ',
'are ',
'you ',
'today ?'=> array (
'march ',
27,
2010
)
),
'out ',
'there !'
);

18
19
20
21
22
23
24
25
26
27

foreach ( $arbore as$k=>$v){


if( is_string ($v)){
echo"$k=>$v ";
}
elseif ( is_array ($v)){
echo"*** RECURSIVITY ";
}
echo PHP_EOL ;
}

Practic nu este nimic nou. Iterm array-ul i am valorile. ns pe linia 23 detectm dac valoarea nsi
este la rndul ei tot un array (precum $arbore, pe care tocmai l iterm), i am " *** RECURSIVITY".
in s subliniez: valoarea $v este un array, i chiar dac se a n interiorul unui array $arbore, este
tot un array, deci $v poate iterat cu exact aceeai bucl foreach cu care iterm $arbore.
Practic, nu trebuie dect s reutilizm codul de pe liniile 19-27. i ce modalitate cunoatem pentru
a reutiliza codul? Exact, funciile!
Deci implementm o funcie
void itereaza_recursiv(array $arbore)
i o apelm, astfel:
18

DOM - document object model

105

Dezvoltare web cu PHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

3.4. STRUCTURI DE DATE

<?php
$arbore = array (
'hello ',
'foo ',
'world '=> array (
'how ',
'are ',
'you ',
'today ?'=> array (
'march ',
27,
2010
)
),
'out ',
'there !'
);

18
19
20
21
22
23
24
25
26
27
28
29
30

function itereaza_recursiv ( $arbore ){


foreach ( $arbore as$k=>$v){
if( is_string ($v)|| is_numeric ($v)){
echo"$k=>$v";
echo PHP_EOL ;
}
elseif ( is_array ($v)){
echo" going into'$k '\r\n";
itereaza_recursiv ($v);
}
}
}

31
32

itereaza_recursiv ( $arbore );

Dup cum observi, funcia itereaza_recursiv() se apeleaz pe ea nsi pe linia 27, ns cu o alt
valoare cu valoarea elementului curent $v, care este tot un array. Pe linia 27 spunem c intrm n
recursivitate. La primul apel, la elementul 'world', intrm n adncimea 1 a arborelui. n cadrul
elementului 'world' se a nc un element la cheia 'today?' care are ca valoare un array. Atunci cnd
se ajunge la el, spunem c intrm n adncimea 2 a recursivitii.
Dup ce am aat valoarea 2010, ieim din recursivitatea de adncime 2, revenind la 1, i ne am iar
n array-ul cu cheia 'world'. ns ajuni aici, ne am iar la sfritul iteraiei, deoarece bucla foreach
ajunge la sfritul array-ului salvat n elementul 'world', deci ieim din recursivitate (i deci din funcia
itereaza_recursiv()), revenind tot n funcia itereaza_recursiv()!
ns acum ne am pe linia 28, i nu ne am la sfritul recursivitii de adncime 0, deci bucla
foreach trece la urmtorul element: 'out'.

Adncimea recursivitii**

Modic funcia itereaza_recursiv() dndu-i semntura:


string itereaza_recursiv(array $arbore, $depth=0)
i modic implementaia astfel nct ecare aare de forma "cheie => valoare" s aib n faa sa un
numr de spaii egal cu adncimea din recursivitate la care se a acel element, structura arborescent
ind astfel evideniat i grac:
0 => hello
1 => foo
going into 'world'
106

Dezvoltare web cu PHP

3.4. STRUCTURI DE DATE

0 => how
1 => are
2 => you
going into 'today?'
0 => march
1 => 27
2 => 2010
2 => out
3 => there!
Funcia nu trebuie s aeze direct cu echo, ci s returneze outputul ca string, din motive de modularizare.
Scriptul trebuie s funcioneze ca script CLI, nu printr-un daemon http, deci pentru a genera o linie
nou n output folosete constanta PHP_EOL, pe care o cunoti deja.
Pn acum am lucrat cu propriile structuri de date recursive. Vei confruntat deseori cu necesitatea
de a inventa astfel de structuri de date, ns i mai des va trebui s procesezi date recursive asupra crora
nu ai control. Un astfel de exemplu este un director, cci un director poate avea iere i alte directoare
n el. Observi recursivitatea?
Lucrul cu iere i directoare se poate face cu ajutorul extensiilor din categoria File System Related
Extensions, mai exact ne intereseaz n special extensia Directory Functions. Din extensia Filesystem
Functions avem nevoie doar de funciile is_dir() i is_file() pentru a verica dac un element este
director sau ier.
ncepem prin doar a itera un director, fr a intra recursiv n alte subdirectoare:
1
2
3
4
5
6
7
8
9
10
11
12

<?php
function display_directory ( $dirpath ){
$dh= opendir ( $dirpath );
while ( $entry = readdir ($dh)){
echo $entry ;
if( is_dir ( $dirpath . DIRECTORY_SEPARATOR . $entry )){
echo DIRECTORY_SEPARATOR ;
}
echo PHP_EOL ;
}
closedir ($dh);
}

13
14

display_directory ( __DIR__ );

opendir() ne returneaz o resurs. Acesta este un alt tip de date fundamental n PHP, ns el nu poate
creat direct de scripturile noastre, ci doar prin intermediul funciilor native PHP, implementate n
extensii.
Deschiznd un director cu opendir() avem acces la aceast resurs i l putem itera.
Cu readdir() citim ecare intrare din acest director, salvnd rezultatul n $entry. Aceast variabil
este e un string, e FALSE, dac am iterat totul, caz n care condiia buclei while va FALSE, deci se
va iei din bucla din uxul de execuie.
Pe linia 6 vericm dac noua intrare este un director, i dac da, am i valoarea
constant DIRECTORY_SEPARATOR. Diferite sisteme de operare folosesc diferite separatoare n cile
ctre iere i directoare. MS Windows folosete \, n timp ce GNU/Linux folosete /. Constanta
DIRECTORY_SEPARATOR va avea mereu valoarea corespunztoare platformei pe care ruleaz scriptul.
Aarea acestei constante este doar un indiciu vizual pentru noi, s tim dac avem de-a face cu un
ier, sau cu un director. n practic, aici ar trebui s intrm recursiv n noul subdirector.
Toate19 directoarele au dou pseudo-directoare n ele: '.' i '..'. Acestea nu sunt directoare n
adevratul sens al cuvntului, ci sunt referine, primul ctre directorul nsui, al doilea ctre directorul
19

Aproape toate

107

Dezvoltare web cu PHP

3.5. CALL STACK

printe. Cu siguran ai folosit deja n HTML ci relative precum


1

<imgsrc="../ img/me.jpg">

De aici vine acel '..'.

Determinarea recursiv a coninutului unui director**

n funcia anterioar, n loc de simpla aare a valorii DIRECTORY_SEPARATOR, vrem s intrm n


directorul respectiv. Extinde i modic funcia astfel nct s aib semntura
array get_directory_structure(string $dir_path)
i s returneze ierele i toate subdirectoarele din directorul $dir_path ntr-un array recursiv.

Aarea unei structuri de date recursive*


Partea I

Implementeaz o funcie
string render_recursive_array_to_ul(array $array)
care accept ca parametru un array (eventual recursiv) i returneaz reprezentarea HTML a acestuia
ntr-o list neordonat (<ul>).
Acestei funcii i vei putea pasa valoarea returnat de un apel la get_directory_structure()
implementat n exerciiul anterior.
Observi cum implementaia de funcii care opereaz doar pe date abstracte (aici: array-uri) duc
automat la reutilizarea i o mai bun modularizare a codului?

Partea II
Extinde funcia astfel nct s accepte i o funcie anonim ca callback:
string render_recursive_array_to_ul(array $array,callback $cb=NULL)
care dac este prezent, este folosit pentru a genera outputul ce trebuie pus ntre <li> i </li>. Semntura
callback-ului trebuie s e
string cb(string $path)

Call Stack
Atunci cnd apelm o funcie, PHP pune contextul actual de execuie pe un stack (operaia push),
i apoi se apeleaz funcia. La ieirea din funcie (cu un return), PHP face un pop pentru acel stack, i
execuia se continu de unde fusese ntrerupt anterior.
Acest stack se numete call stack, ecare element de pe acest stack ind numit call frame.

108

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

Fiiere multiple
Pn acum ne-am structurat scripturile n funcii reutilizabile pe de o parte, i pe de alta separnd
business logic de view logic, ns totul se aa ntr-un singur ier. Nu puteam refolosi nici logica, nici
prezentarea, separate una de alta.
PHP ne pune la dispoziie patru directive pentru includerea unui ier n alt ier .php. Primele dou
se numesc include i require. Sintaxa este destul de intuitiv:
include <string>;
require <string>;
Exemplu:
index.php
1
2
3
4

<?php
if(isset ( $_GET ['nume '])&& is_string ( $_GET ['nume '])){
$nume = $_GET ['nume '];
}

5
6
7
8
9

if(isset ( $nume )){


include 'greet_nume .php ';
}
include 'greeting_form .php ';

greet_nume.php
1

Salut <?phpecho $nume ;?>.

greeting_form.php
1
2
3
4

<form method ="GET" action =" index .php">


<input type="text"name="nume"/>
<input type=" submit " value =" greet "/>
</form >

Bineneles exemplul nostru nu este att de complex nct avantajele s devin evidente. Un avantaj
posibil ar c putem schimba modul de funcionare extrem de uor, fr a modica nici un alt ier n
afara lui index.php.
Aa cum este acum, scriptul aeaz formularul indiferent dac avem numele ca input sau nu. Am
putea schimba rapid n aarea formularului doar dac numele nu a fost trimis de utilizator, modicnd
index.php astfel:
index.php
6
7
8
9
10
11

if(isset ( $nume )){


include 'greet_nume .php ';
}
else{
include 'greeting_form .php ';
}

fr a ne atinge de nici un alt ier.


Alt avantaj e c am putea refolosi greet_nume.php oricnd vrem s salutm pe cineva. Nu ar trebui
dect s ne asigurm c exist variabila $nume, deoarece aceasta este folosit de acel script.
Diferena dintre include i require const n cum trateaz PHP absena ierului inclus. Cu
include, PHP genereaz o avertizare dar continu execuia. Cu require, execuia se oprete complet
dac ierul nu exist sau PHP nu l poate citi. De aceea, este recomandat s folosim require atunci

109

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

cnd tim c aplicaia nu ar avea oricum s-i ndeplineasc (mcar parial) execuia fr ierul php pe
care vrem s-l injectm n runtime-ul php.

Sub MS Windows, \trebuie precedat de un alt \n stringurile interpolate atunci cnd sunt
declarate ci pentru lesystem.

Celelalte dou directive pentru includerea codului de iere este familia *_once. Sintaxa:
include_once <string>;
require_once <string>;
Aa cum le spune i numele, aceste constructe vor include ierul doar o singur dat. Asta este foarte
util dac ierul inclus conine implementrile unor funcii, deoarece, dac am implementa o funcie cu
acelai nume de mai multe ori, PHP ne-ar spune c nu putem redeclara acea funcie. Exemplu:
1
2
3
4

<?php
include_once 'functions .php ';
include_once 'functions .php ';// nuvamaifi inclus incaodata
echofoo ();

Unde funcia foo() este implementat n ierul functions.php. Totui n acest caz ar mai bine s
folosim require_once, astfel nct dac ierul functions.php nu exist, execuia s e ntrerupt din
start. Nu are rost s ncercm s executm un cod care apeleaz o funcie care nu exist, deoarece ierul
n care ar trebui s e implementat nu exist.

3.6.1 abloane
n exemplul anterior, greet_nume.php se numete ablon (en. template). Folosirea lui este ns
dependent de existena unei variabile numit $nume, ceea ce face template-ul nostru s e cuplat de
aceast variabil, la fel cum i cuvntul cheie global cupleaz numele unei variabile de o funcie.
Putem decupla foarte elegant orice template de variabilele folosite n el crend o funcie precum:
void render(string $template, array $vars=NULL)
unde $template este calea ctre un ier .php folosit ca template, iar $vars este un array asociativ.
Acest array va iterat ca n listingul 2.14, crend astfel variabilele cerute de template-ul $template.
Aceste variabile vor locale funciei render(),20 deci nu vor polua nici un scope, ind terse automat de
PHP atunci cnd uxul de execuie iese din funcie. n acelai timp, variabilele specice template-ului
nu vor cuplate de scope-ul global, aa cum $nume folosit de greet_nume.php era cuplat de $nume din
scope-ul global (index.php).
Dup ce variabilele variabile au fost create, o simpl instruciune de includere a ierului va genera
outputul.
Dac funcia nu primete un al doilea parametru de la apelant, atunci $vars va avea valoarea NULL,
i nu ar trebui s mai crem variabilele variabile, ci doar s includem template-ul.

O funcie render()
Partea I

Scrie o funcie
void render(string $template, array $vars=NULL)
care creaz variabile variabile pe baza array-ului asociativ $vars i apoi include $template.
Exemplu de apelare a acestei funcii:
20

Se vor aa doar n scope-ul local al funciei

110

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

render (' greet_nume .php ', array ('nume '=> $nume ));

Partea II
Rescrie funcia render() folosind funcia intern extract().
n exemplul din exerciiul anterior am apelat funcia cu parametrul array('nume' => $nume). n
PHP exist funcia compact() care poate crea un array asociativ cu numele variabilelor ca chei, i valorile
acestora ca valori n array. Este o funcie foarte util atunci cnd numele variabilelor din scope-ul actual
(n cazul de fa cel global) sunt numite la fel ca variabilele folosite n template-ul n cauz.

3.6.2 Primul site complet


Hai s vedem cum putem folosi toate lucrurile nvate sau nu pn acum. Includ i lucrurile
nenvate, deoarece m atept s te documentezi din manual atunci cnd ntlneti o funcie necunoscut.
O vom lua gradual, adugnd treptat funcionalitate, i deci i complexitate.
Vrem s facem un site personal cu cteva pagini. ntregul site va prezenta pe toate paginile un meniu
comun cu lista paginilor existente.
<html>
Content
Menu

</html>

Figura 3.5: Layout site personal


Toate paginile vor arta similar, doar coninutul efectiv al ecrei pagini ind diferit. Spunem c
site-ul folosete un template. Acesta va arta ca n gura 3.5.

Creaz template

Creaz un ier XHTML 1.1 structurat ca n gura 3.5. Alegerea culorilor i aezarea n pagin sunt
lsate la atitudinea ta, dar meniul trebuie s e denit aa:
1

<divid="menu">

2
3

</div >

iar continutul aa:


111

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

<divid=" content ">

2
3

</div >

Pentru site-ul nostru, am tentai s punem acest template n index.php. Asta nu ar o decizie
bun, deoarece nu am putea reutiliza template-ul n alte locuri. index.php ar trebui doar s coordoneze
conlucrarea dintre business logic i view logic. Deci pune template-ul creat ntr-un ier nou numit
layout.php. Acum crem i index.php, care va aa template-ul. Ulterior urmeaz s adugm i
procesrile (business logic) corespunztoare:
index.php
1
2
3

<?php
require_once 'functions .php ';
// herebe processing

4
5

render (' layout .php ');

Creaz i ierul functions.php i pune n el implementaia funciei render() creat n unul din
exerciiile anterioare.
Acum hai s facem layout-ul s foloseasc cteva variabile: $title, $menu, i $content. nlocuiete
astfel nct s ajungi la:
<title ><? phpecho $title ;?></ title >
<divid =" menu "><?phpecho $menu ;?></div >

i
<divid =" content "><?phpecho $content ;?></div >

Deoarece template-ul folosete acum aceste variabile, trebuie s i le exportm. Deci adaug un array
asociativ corespunztor:
index.php
1
2
3
4
5
6
7

<?php
require_once 'functions .php ';
$tpl_vars = array (
'title '=>'MyHomepage ',
'menu '=>'nomenuyet ',
'content '=>'no content yet '
);

8
9

render (' layout .php ', $tpl_vars );

ns am spus c vrem s am diferite pagini, ecare pagin cu coninutul ei, i n plus ecare pagin
s aib un link n meniu.
Cu siguran ne-am putea apuca s mzglim nite cod la grmad, i cu siguran ne va iei ceva
aspectuos. Dar cel mai probabil nu ne va iei ceva reutilizabil dac nu stm s ne gndim puin mai
profund i mai sistematic de ce avem nevoie.
nc o dat, rezumm: o pagin are
un titlu, pus n <title></title> n template
un coninut
un meniu
112

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

n exemplul de mai sus, coninutul este la noi un string. ns acest coninut va diferi de la pagin la
pagin, i cel mai probabil va foarte lung.
Am putea teoretic s punem coninutul ecrei pagini ntr-un string, ns asta ar face codul foarte
greu de citit i mentenat. Mult mai curat ar dac am considera un nume de ier ca ind caracteristica
coninut a acelei pagini. Altfel spus, o pagin ar consista din:
un titlu, pus n <title></title> n template
un ier cu coninutul efectiv
un meniu
Deci am putea crea o structur de date abstract care s conin o pagin. Deoarece avem o serie de trei
caracteristici pentru o pagin, putem salva aceste informaii despre ecare pagin ntr-un array asociativ:
1
2
3
4
5
6
7
8
9
10

$home = array (
'title '=>'Bineaivenit ',
'content '=>'home.php ',
'menu '=>'nomenuyet '
);
$about = array (
'title '=>'Despre mine ',
'content '=>'despre .php ',
'menu '=>'nomenuyet '
);

Nu m-am grbit s creez i meniul pentru ecare pagin, deoarece am realizat c acest meniu ar putea
determinat programatic, pe baza variabilelor precum $home sau $about. Ce ar implica generarea
automat a meniului pentru ecare pagin? Exact! Ar implica iterarea acestor variabile. ns noi nu
putem itera variabile. Putem itera array-uri. De aici ne vine ideea genial de a salva toate paginile
ntr-un array asociativ. Hai s vedem cum va arta index.php
1
2

<?php
require_once 'functions .php ';

3
4
5
6
7
8
9
10
11
12
13
14
15

$pages = array (
'home '=> array (
'title '=>'Bineaivenit ',
'content '=>'home.php ',
'menu '=>'nomenuyet '
),
'about '=> array (
'title '=>'Despre mine ',
'content '=>'despre .php ',
'menu '=>'nomenuyet '
)
);

16
17
18
19
20
21

$tpl_vars = array (
'title '=>'MyHomepage ',
'menu '=>'nomenuyet ',
'content '=>'no content yet '
);

22
23

render (' layout .php ', $tpl_vars );

Realizm dou lucruri:


variabila $tpl_vars devine inutil toate informaiile se a acum n $pages, chiar dac nu n
exact aceeai form. De exemplu, va trebui s gsim o metod de a citi ierul .php cu coninutul,
deoarece nu vom mai avea la dispoziie coninutul efectiv ca string
113

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

variabila $pages este ca un fel de variabil de congurare. Atunci cnd am separat business logic
de view logic,21 am spus c misiunea lui index.php este s coordoneze conlucrarea dintre diferite
componente, deci dei este posibil s punem conguraiile ntr-un astfel de script de coordonare,
mult mai curat ar s separm i congurarea de celelalte dou procese izolate, i anume business
logic i view logic
Pentru primul punct avem puin mai mult de munc, dar pentru al doilea exist o soluie foarte elegant.
Familia de directive include nu numai c include un ier, dar i este evaluat ca valoarea returnat de
ierul inclus.22 Astfel am putea avea un ier de congurare pages.php:
pages.php
1
2
3
4
5
6
7
8
9
10
11

<?php
return array (
'home '=> array (
'title '=>'Bineaivenit ',
'content '=>'home.php '
),
'about '=> array (
'title '=>'Despre mine ',
'content '=>'despre .php '
)
);

Iar index-ul nostru va deveni mult mai curat:


1
2
3

<?php
require_once 'functions .php ';
$pages = require_once 'pages .php ';

4
5

render (' layout .php ');

Pentru a aa diferite pagini, nu trebuie dect s acceptm un parametru prin $_GET n funcie de
care s decidem care dintre pagini trebuie aat.

Fiierul de congurare pages.php constituie ceea ce putem numi conguration logic. n


interiorul lui putem genera chiar i programatic conguraia, folosind condiii, bucle, i orice
altceva ce ine de controlul uxului de execuie. Trebuie ns s m ateni s nu denaturm
natura acelor informaii care urmeaz a returnate. Iar de ndat ce am returnat o conguraie,
este bine s nu ne mai atingem de ea. Altfel riscm s alergm dup greeli de programare greu
de identicat.

Vom modica corespunztor index.php:


index.php
1
2
3

<?php
require_once 'functions .php ';
$pages = require_once 'pages .php ';

4
5
6
7
8
9
10

if(isset ( $_GET ['show '])&& array_key_exists ($_GET ['show '], $pages )){
$page = $_GET ['show '];
}
else{
$page ='home ';
}

11
12

21
22

render (' layout .php ', $pages [ $page ]);


folosind funcia proprie render()
Astfel de detalii, dar multe altele, pot citite n manualul PHP, capitolul Language Reference

114

Dezvoltare web cu PHP

3.6. FIIERE MULTIPLE

ns asta ne va aa ca coninut numele ierelor, nu coninutul acelor iere, care nici mcar nu exist
nc.
Deci creaz mai nti un subdirector pages i n el dou iere home.php i despre.php cu un coninut
HTML la alegere. Apoi modic layout-ul astfel nct s includ ierul pe care-l primete n variabila
$content, n loc s l aeze direct:
<divid=" content ">
<?php include __DIR__ . '/ pages /'. $content ;?>
</div >

Un ultim lucru mai avem de fcut: s construim meniul dinamic, pe baza informaiilor din $pages.
Membrul 'menu' al ecrei pagini din $pages nu i are rostul, constituie doar informaii redundante ce
pot deduse din $pages.
Deci vom crea o funcie care ia ca parametru un array precum $pages i genereaz un meniu HTML.
Deoarece o astfel de funcie are rol ajuttor, i n fapt marginal funcionrii aplicaiei dincolo de formatul
HTML, numim o astfel de funcie un helper. Funcia va avea semntura:
string build_menu_from_pages(array $pages)
Implementaia o adugm n ierul functions.php
functions.php
function build_menu_from_pages ( $pages ){
$r='<ul >';
foreach ( $pages as $pagename => $metadata ){
$r.='<li ><ahref ="? show ='. $pagename .'">'. $metadata ['title '].'</a></li >';
}
return $r.'</ul >';
}

Felicitri. Acum nu numai c ai un site, dar ai o structur exibil pe a crei fundaie poi aduga
uor pagini noi. Pentru a aduga o pagin nou de exemplu, tot ce trebuie s faci este s o creezi n
subdirectorul pages i s o nregistrezi ca pagin valid n pages.php, alturi de metadate despre pagin
precum titlul paginii. n rest, nu trebuie s te atingi de nici un alt cod, nu trebuie s mui sau s editezi
cod, iar meniul va construit automat.
Pentru recapitulare, gura 3.6 prezint nc o dat structura de iere creat i scopurile lor.

index.php

coordoneaz conlucrarea dintre


business logic, view logic i congurare

layout.php

ablonul site-ului

functions.php

funcii utile

pages.php
pages/
despre.php

paginile efective
i congurarea
lor

home.php

Figura 3.6: Structura ierelor unui site simplu

115

Dezvoltare web cu PHP

3.7. DIRECTORUL CURENT DE LUCRU

mbuntete-i pagina personal*


Partea I

Momentan meniul conine link si pentru pagina activ, ceea ce nu prea are sens. Extinde funcia
build_menu_from_pages astfel nct s nu genereze link pentru pagina activ momentan, ci doar s o
aeze n lista neordonat ca text.

Partea II
index.php conine business logic-ul site-ului tu. Extinde acest business logic astfel nct pentru
paginile inexistente s arate o pagin notfound.php. home.php trebuie s rmn n continuare pagina
de start standard a site-ului.

Partea III
Adaug nc o pagin Despre tine care aeaz informaii despre vizitator din array-ul superglobal
$_SERVER.
Dac tii CSS, stilizeaz site-ul aa nct s e mai aspectuos. Nu va trebui s modici n nici un fel
layout-ul sau paginile individuale. Vei lucra doar cu CSS.
Din partea I a exerciiului se observ n practic un alt avantaj al funciilor: nu trebuie s editezi
multe iere n lungul i-n latul proiectului, nu te atingi de business logic sau de view logic deoarece nu
modici modul fundamental de funcionare al acestora. Doar mbunteti funcia, iar modicrile sunt
preluate automat n toate locurile de unde aceasta este apelat.

Directorul curent de lucru


Cile relative ctre iere i directoare, sunt relative la ceea ce numim current working directory. La
runtime (n timpul execuiei scriptului), putem aa CWD-ul cu funcia getcwd(), i schimba CWD-ul
cu chdir().
n exemplele anterioare, instruciuni precum
1
2

<?php
require_once 'functions .php ';

au funcionat deoarece directorul curent de lucru '.' este specicat n mod standard n directiva
php.ini include_path. Modul corect de a include un ier, fr a ne baza pe faptul c acesta se
a n include_path, ar
1
2

<?php
require_once './ functions .php ';

unde '.' se refer la CWD.


Dac avem ns un scenariu mai complex, cu urmtoarele iere:

Figura 3.7: Scenariu includere


index.php
1
2

<?php
require_once './ functions /foo.php ';

116

Dezvoltare web cu PHP

3.7. DIRECTORUL CURENT DE LUCRU

3
4

echo'index .phpestein directorul ',__DIR__ , PHP_EOL ;

5
6
7
8

echo'apelul lafoo () genereaza :';


foo ();
echo PHP_EOL ;

functions/foo.php
1
2
3
4
5

<?php
require_once './ foo/ foobar .php ';
function foo (){
echo __DIR__ ;
}

functions/foo/foobar.php
1
2
3

<?php
function foobar (){
}

atunci toate ierele sunt incluse prin prisma ierului index.php, deci CWD-ul este directorul n
care se a acest ier. Asta nu este o problem pentru linia 2 din index.php, deoarece directorul '.'
coincide cu directorul n care se a index.php.
ns devine o problem atunci cnd din ierul inclus foo.php vrem s includem un alt ier dintr-un
alt subdirector functions/foo/, deoarece CWD-ul nu se schimb, i deci, relativ la directorul n care se
a index.php, nu exist un subdirector ./foo/foobar.php.
O metod foarte elegant la problema asta este s denim o constant n index.php, constant care
va folosit la includerea ierelor. Astfel am avea:
index.php
1
2
3

<?php
const APP_ROOT = __DIR__ ;
require_once APP_ROOT . '/ functions /foo.php ';

4
5

echo'index .phpestein directorul ',__DIR__ , PHP_EOL ;

6
7
8
9

echo'apelul lafoo () genereaza :';


foo ();
echo PHP_EOL ;

functions/foo.php
1
2
3
4
5

<?php
require_once APP_ROOT . '/ functions /foo/ foobar .php ';
function foo (){
echo __DIR__ ;
}

Cu aceast tehnic vom avea n lungul i-n latul aplicaiei constanta APP_ROOT care conine mereu calea
ctre directorul n care se a n index.php, indiferent de ierul prin care trece momentan uxul de
execuie.
Cu adevrat exibil devine aceast metod atunci cnd avem aplicaii multiple care folosesc un set
comun de funcii. Nu va trebui s copiem ierele de colo colo, ci vom dezvolta doar o singur versiune
a acestor funcii comune, denind o constant de genul APP_LIB cu calea ctre directorul ce conine iere
PHP cu implementrile funciilor noastre. Din a doua aplicaie care dorete s foloseasc funciile primei
aplicaii, nu trebuie dect s denim APP_LIB ca calea ctre directorul cu funcii din prima aplicaie, cea
original.
117

Dezvoltare web cu PHP

3.8. FORMULARE II. FILE UPLOADS

i mai curat din punct de vedere organizatoric este s punem toate aceste funcii ntr-o locaie neutr,
astfel nct s nu aparin nici unui proiect, i din toate proiectele s denim calea ctre acea locaie.
O alt tehnic implic folosirea tocmai a acestei constante magice __DIR__.
Cu aceast tehnic nu mai e nevoie s denim constante globale precum APP_ROOT, ns nici nu
mai putem reutiliza poriuni de funcionalitate n lungul i-n latul diferitelor proiecte independente unul
de cellalt.
Un astfel de cod ar arta astfel:
index.php
1
2
3

<?php
require_once './ functions /foo.php ';
foo ();

functions/foo.php
1
2
3
4

<?php
require_once __DIR__ . '/foo/ foobar .php ';
function foo (){
}

functions/foo/foobar.php
1
2
3

<?php
function foobar (){
}

Includerea ierelor ar trebui s o faci mereu folosind ci absolute, precum o constant global
aplicaiei sau cu constanta magic __DIR__.
Atunci cnd foloseti ci absolute, PHP nu trebuie s ia la rnd cile din include_path, ceea ce
l absolv pe PHP de multe accese ale hard-disk-ului - aceste accese ind destul de costisitoare.

Formulare II. File uploads


Cu PHP, poi oferi utilizatorului posibilitatea de a salva ierele proprii pe hard disk-ul serverului.
Este ceea ce numim le upload.
Formularele care conin cmpuri pentru upload trebuie s e trimise cu metoda HTTP POST, i s
e codate ca multipart/form-data.
Un exemplu:
index.php
1
2

<?php
require_once __DIR__ . '/ functions .php ';

3
4
5
6
7
8
9
10
11
12
13

echo'<pre >';
var_dump ( $_FILES );
echo '</pre >';
?>
<form enctype =" multipart /form -data" method =" POST">
<input type =" hidden "name =" MAX_FILE_SIZE "
value =" <? phpecho return_bytes ( ini_get (' upload_max_filesize '));?>"/>
<input name =" myfile "type =" file"/>
<input type =" submit " value =" Send"/>
</form >

118

Dezvoltare web cu PHP

3.8. FORMULARE II. FILE UPLOADS


functions.php

<?php
function return_bytes ($val){
$val=trim($val);
$last =$val[ strlen ($val) -1];
switch ( $last ){
case'g ':
case'G ':
$val*= 1024;
case'm ':
case'M ':
$val*= 1024;
case'k ':
case'K ':
$val*= 1024;
}
return $val;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Codul este destul de sugestiv. La primirea ierelor (cu succes sau cu erori, nu conteaz), informaiile23
despre ele vor disponibile n array-ul superglobal $_FILES.
Elementul 'error' din ecare set de metadate va conine codurile de eroare pe care le poi compara
cu constantele specice24 pentru a determina cauza erorii.

Este recomandat s foloseti aceste constante predenite, precum UPLOAD_ERR_OK, n loc de


valorile numerice concrete, pentru o mai bun portabilitate.

Elementul tmp_name este calea absolut ctre ierul efectiv. Atunci cnd utilizatorul uploadeaz
un ier, acesta primete un nume temporar aleatoriu, i este salvat acolo unde specic directiva de
congurare php.ini upload_tmp_dir.
Numele real al ierului, aa cum a fost uploadat de utilizator, se a n 'name'.
'type' este tipul MIME al documentului.
Alte directive care inueneaz upload-ul de iere sunt
post_max_size pentru mrimea total a datelor trimise prin POST, mrime care include cumulativ
mrimea tuturor datelor trimise, nu numai a ierelor
max_input_time limiteaz timpul pe care PHP are voie s l petreac procesnd datele trimise.
Acest timp depinde n mare msur de rata de upload a clientului i de rata de download a serverului
file_uploads poate activa sau dezactiva uploadul de iere dintr-un foc
max_file_uploads limiteaz numrul de iere ce pot uploadate de client ntr-o singur cerere
HTTP
Din moment ce ierul uploadat se a ntr-un director ce nu aparine aplicaiei noastre, cu un nume
aleatoriu, va trebui s l mutm n interiorul aplicaiei noastre. Pentru a verica dac un ier este un ier
uploadat folosim is_uploaded_file(), iar pentru a muta acel ier, folosim move_uploaded_file().

Deschide manualul PHP i documenteaz-te despre aceste funcii. Manualul conine exemple
de utilizare i o mulime de comentarii din partea altor utilizatori din care cu siguran poi
nva cte ceva.

23
24

metadatele
http://www.php.net/manual/en/features.file-upload.errors.php

119

Dezvoltare web cu PHP

3.9. LUCRUL CU FIIERE

Remote le storage**
Partea I

Creaz o aplicaie care permite utilizatorilor s uploadeze iere pe serverul tu.


Utilizatorii vor trebui s introduc i un nume secret care va folosit de aplicaie pentru crearea unui
subdirector corespunztor, director n care va pus ierul uploadat.
Fiierele uploadate se vor aa deci n directorul uploads/<nume secret>/. Astfel, utilizatori care se
cunosc ntre ei vor putea uploada colaborativ iere, lucrnd cu un <nume secret> comun.
Folosete funcii ca is_dir() i mkdir(). Exploreaz manualul dac te loveti de necesitatea folosirii
altor funcii.
Nu uita s verici toate erorile posibile i imposibile, i c aplicaia trebuie s se comporte normal i
s genereze cod XHTML 1.1 valid, chiar i atunci cnd aplicaia ta genereaz erori.
Nu uita nici de separarea business logic-ului de view logic. Construiete-i aplicaia ct mai
modularizat posibil.

Partea II
Ce guri de securitate identici?

Lucrul cu iere
Pn acum am lucrat cu iere ca entiti opace, fr a citi din sau a scrie n ele.
PHP pune la dispoziie funcii pentru lucrul cu iere. Aa cum n paginile trecute am deschis un
director pentru a-l itera, i apoi l-am nchis, eliberndu-l, tot la fel putem lucra i cu informaiile salvate
n iere.
Pentru a opera pe un ier, trebuie s l deschidem cu fopen(). Ne alegem cu un le handler care va
pasat ca parametru funciilor urmtoare de manipulare a ierelor.
Deschiderea ierelor se face n moduri precum citire, scriere sau adugare. O list complet
ale acestor moduri se gsete pe pagina fopen() din manualul PHP.
Atunci cnd deschidem ierul, dispunem de un cursor25 pe care l putem plimba n lungul i-n latul
ierului. n funcie de modul n care am deschis ierul, acest cursor se va aa imediat dup deschiderea
ierului cu fopen() e la nceputul, e la sfritul ierului. n modul read, cursorul se va aa la nceput.
n modul append, la sfrit.
Citirea din ier o facem cu fread(), funcie creia trebuie s-i spunem i ce lungime maxim n bytes
vrem s aib segmentul de informaie citit. La apelarea acestei funcii, cursorul va naintat cu numrul
de bytes citii.
Deoarece nu tim ce mrime are ierul, va trebui s citim n mod repetat din ier, ntr-o bucl,
pn cnd ne am la sfritul ierului (en. end of le), prescurtat EOF. Pentru a testa dac am ajuns
la EOF, folosim funcia feof().
Dup ce am terminat de operat pe ier, trebuie s-l nchidem cu fclose().

Citete din ier

Scrie un program care citete un numr aleatoriu de bytes ntre 1 i 32 dintr-un ier deja existent i
aeaz stringurile citite la ecare iteraie n cte un bloc HTML <pre></pre>.
Dac ierul nu este readable, programul trebuie s arate un mesaj de eroare corespunztor.
Pentru generarea de numere aleatoare folosete funcia rand() din extensia Math a categoriei de
extensii Mathematical Extensions.
25

Numit i le pointer n manualul PHP.

120

Dezvoltare web cu PHP

3.9. LUCRUL CU FIIERE

Citete cu atenie paginile din manual ale funciilor pentru lucrul cu iere menionate mai sus,
seciunile User Contributed Notes i exploreaz i alte posibiliti dincolo de ceea ce te intereseaz pentru
rezolvarea acestui exerciiu urmnd link-urile din seciunile See Also ale acestor funcii.
De multe ori vom nevoii s structurm informaiile aate n iere. De exemplu hai s ne imaginm
c vrem s facem un guestbook.
Asta nseamn c utilizatorul intr pe pagina noastr i completeaz cmpuri precum nume i
coninut. Teoretic am putea citi aceste informaii i le-am putea aduga la sfritul unui ier care
ar avea funcia de baz de date. Acest ier ar conine toate impresiile lsate de toi vizitatorii notri.
Dar ce facem dac vrem s editm o anumit intrare? Ar trebui s deschidem ntregul ier i s
navigm pn la intrarea n cauz pentru a o edita. n afar de asta, ne-ar greu s identicm bucata
de text pe care o vrem.
Pentru a structura informaiile dintr-un ier, e sucient s introducem o sintax nou. De exemplu,
am putea spune c cele dou cmpuri de date nume i text sunt separate de caracterul |. Baza noastr
de date ar putea arta astfel:
Flavius|Hello world
Florin|Hello back
Ce se ntmpl dac numele meu este Fla|vius? Caracterul separator | va trebui escaped i el.
Din fericire exist un format de date deja larg rspndit iar PHP ne pune la dispoziie funcii pentru
lucrul cu el. Formatul se numete comma-sepparated values (abv. CSV). Separatorul acestui format este
virgula, iar funciile fac escaping automat. Aceste funcii sunt str_getcsv(), fgetcsv(), fputcsv().
CSV este un format ce se preteaz pentru date tabelare. Un alt format este INI. Formatul unui ier
.ini este
;this is a comment
[section1]
key1=value1
key2=value2
[section2]
key1=value1
array[]=value2
array[]=value3
Dup cum putem deduce din exemplu, formatul .ini se preteaz pentru perechi de valori, numite i
dicionare. Adiional, aceste perechi pot grupate n seciuni.
Pentru lucrul cu acest format avem la dispoziie funciile parse_ini_string() i parse_ini_file().
Manualul PHP conine multe exemple i detalii despre aceste funcii i formate de date.

3.9.1 Filesystems
Un lesystem (abv. FS) este un mod de organizare a ierelor i directoarelor pe hard disk. Exist
nenumrate astfel de lesystems, specice unor anumite sisteme de operare, sau create pentru a rezolva
anumite tipuri de probleme. De exemplu, utilizatorii Microsoft Windows folosesc de obicei NTFS,
utilizatorii *NIX ext2, ext3 sau ReiserFS, iar pentru accesarea transparent a ierelor de pe un alt
calculator conectat prin reea de nodul curent se poate folosi NFS (en. Network File System).
Sub GNU/Linux exist ns mai multe tipuri de iere: ierele normale, directoarele, link-uri
simbolice (en. symlinks), device, named pipe i unix socket.
Deoarece nu tim pe ce fel de platform va rula aplicaia (scriptul) nostru, este imperativ s vericm
dac ceea ce urmeaz s deschidem este ntr-adevr un ier sau un director cu is_file() i respectiv
is_dir().
121

Dezvoltare web cu PHP

3.10. COOKIES, SESIUNI, AUTENTIFICARE

Unele lesystems ofer posibilitatea de a specica un proprietar al unui ier sau director, sau drepturi
de acces. De aceea este recomandat s foloseti funcii precum is_readable() sau is_writable() nainte
de a deschide ierele sau directoarele n cauz pentru citire din sau scriere n ele.
n cazul n care creezi programatic iere, nu uita c umask-ul procesului PHP determin drepturile
standard de acces ale ierului nou creat. Deasemenea nu uita c utilizatorul sub care ruleaz parserul
PHP va proprietarul ierelor create programatic.26 Pentru a schimba sau verica aceste setri, PHP
pune la dispoziie funcii precum umask() i chmod().
Pentru a i testa extensiv aplicaiile pe diferite platforme precum MS Windows sau GNU/Linux, i
recomand s foloseti programe de virtualizare. O list de resurse despre acestea i despre GNU/Linux
este pus la dispoziie de comunitatea phpro prin intermediul articolelor.

Remote le storage cu editare text on-site*

Extinde aplicaia creat la exerciiul anterior astfel nct utilizatorii s poat edita ierele de tip
text direct pe site, cu un textbox.

Cookies, sesiuni, autenticare


Pentru a nelege cum funcioneaz autenticarea, trebuie s reiterm lucrurile nvate n primul
capitol despre HTTP.
Clientul stabilete o conexiune TCP/IP cu daemonul i i trimite o cerere n formatul HTTP. Aceast
cerere este format din request line i request headers.
Daemonul rspunde cu response headers i response body. Dup ce aceste lucruri au avut loc,
conexiunea dintre client i daemon este nchis. Din acest motiv, spunem c HTTP este un protocol
stateless.
Clientul vine i pleac dup cum poftete, se conecteaz, i ia datele, i apoi pierdem legtura cu el.
Putem ns s i trimitem nite informaii speciale pe care un client (un browser) cooperativ ar trebui
s le salveze pe hard disk-ul utilizatorului i s ni le trimit iar atunci cnd se conecteaz ulterior la noi
i ne cere ceva. Aceste buci de informaii se numesc cookies.
Mrimea maxim a unui cookie este de 4 kb n aproape toate browserele moderne i des ntlnite, iar
numrul de cookies pe care un domeniu are voie s le seteze variaz de la browser la browser. n trecut
limita era de 20, dar chiar i asta este mult pentru o aplicaie tipic, modern, scris n PHP, unde de
obicei un singur cookie este sucient.
Deci hai s ne jucm cu cookies:
Folosirea cookie-urilor
1
2
3

<?php
setcookie ('random ',rand (100 ,999));
var_dump ( $_COOKIE );

Linia 2 seteaz un cookie numit random. Vom crea o cerere HTTP cu telnet pe portul 80:
GET /cookie.php HTTP/1.1
Host: localhost
S zicem c noi, folosind telnet, suntem un browser care coopereaz urmnd exact ceea ce ne spune
daemonul s facem. Dac n exemplul de mai sus am primit ca rspuns
26

De obicei numele utilizatorului din sistem este nobody, httpd sau http, dar nu este recomandat s te bazezi pe
astfel de standarde nescrise.

122

Dezvoltare web cu PHP

3.10. COOKIES, SESIUNI, AUTENTIFICARE

Set-Cookie: random=139
atunci, la vizita urmtoare, i vom pasa acest cookie daemonului, cu valoarea pe care ne-a transmis-o.
Deci trimitem cererea:
GET /cookie.php HTTP/1.1
Host: localhost
Cookie: random=139
i primim rspunsul
HTTP/1.1 200 OK
Date: Thu, 21 Oct 2010 13:20:17 GMT
Set-Cookie: random=278
array(1) {
["random"]=>
string(3) "139"
}
Cookie-ul numit random are acum alt valoare, 278, aa cum este generat de linia 2 din script. ns
array-ul superglobal $_COOKIE nu conine acea nou valoare generat i trimis clientului. $_COOKIE
conine doar ceea ce a fost trimis de client.

Din aceasta deducem c $_COOKIE conine tot input, i ca orice input, trebuie vericat, ltrat
i sanitizat.

Al treilea parametru al funciei setcookie() este timestamp-ul pn cnd va valabil acel cookie.
Dac nu e specicat, un browser poate terge acel cookie de ndat ce este nchis.
Timestamp reprezint numrul de secunde care au trecut de la 1 ianuarie 1970. Se mai numete i
UNIX timestamp. Numrul de secunde se calculeaz n fusul orar GMT.27 Pentru a terge un cookie,
pur i simplu setm data expirrii n trecut.
Pentru restul parametrilor ar trebui s consuli manualul PHP. Dac ai ntrebri despre folosirea
cookie-urilor, comunitatea phpro i st la dispoziie.
Cookie-urile sunt utile atunci cnd vrei s salvezi preferinele vizitatorului pe site. De exemplu
indiciile vizuale precum limba preferat n care ar trebui aat site-ul sau care meniuri sunt vizibile i
care nu.
Cookie-urile nu ar trebui folosite pentru salvarea datelor sensibile sau personale precum username,
parol, sau orice alte date care nu vrei s e setate aleatoriu de client. Pentru c nu uita, aceste informaii
sunt lucruri pe care clientul le poate scrie dup buna sa plcere, aa cum am fcut-o noi cu telnet.
Pentru a salva informaii compozite28 n cookies poi serializa i deserializa informaiile folosind
diferite formate, e inventate de tine, e puse la dispoziie de PHP:
nativ PHP: serialize() i unserialize()
URL-encoded: http_build_query() i parse_str()
JSON: json_encode() i json_decode()
27
28

Deoarece are decalaj 0


adic array-uri

123

Dezvoltare web cu PHP

3.10.1

3.10. COOKIES, SESIUNI, AUTENTIFICARE

Sessions

O form special de cookie este aa numita session cookie. O session cookie nu conine informaii
preioase pentru un eventual atacator, ci un simplu ID unic. Numele cookie-ului care va conine ID-ul
poate obinut sau setat cu session_name().
Informaia salvat n acest cookie, adic ID-ul, poate obinut cu session_id().
nainte de a lucra totui cu sesiuni, trebuie s apelm session_start(). Deoarece pornirea
subsistemului PHP pentru sesiuni implic adugarea unui header Set-Cookie, apelul la aceast funcie
trebuie fcut nainte de a scrie orice n response body. Cci dac am scris ceva n response body (de
exemplu cu echo), atunci response header-ele sunt deja trimise, deci e prea trziu s mai trimitem un
cookie clientului.
Asta ne spune i eroarea din acest script:
Headers already sent
1
2
3

<?php
echo'hello world ';
session_start ();

i anume
Warning: session_start(): Cannot send session cookie - headers already sent
Dup ce am pornit sesiunea, putem salva informaii n array-ul superglobal $_SESSION. Dar dac
informaiile nu vor salvate n cookie-ul cu numele session_name(), atunci unde vor salvate?
Rspunsul: n iere. Directiva php.ini session.save_path ne spune unde se a aceste iere. Fiierele
vor numite dup ID-ul sesiunii. Hai s vedem practic cum funcioneaz acest mecanism:
Understanding Sessions
1
2
3
4

<?php
session_start ();
$_SESSION ['username ']='flav ';
echo'Datele salvate in $_SESSION seaflain fisierul : '. session_save_path ().'/sess_ '.
session_id ();

Deschiznd ierul n care ne spune acest script c avem datele, vedem:


username|s:4:"flav";
Ceea ce vedem aici sunt datele salvate n $_SESSION, numai c sunt serializate n formatul specic
modulului session. Conceptul de serializare nsui l-am cunoscut deja prin formatul json sau funcii
precum serialize() menionate anterior.
Funcia session_start() nu face nimic altceva dect s citeasc id-ul din cookie-ul
cu numele returnat de session_name()29 , i s deserializeze informaiile aate n ierul
session_save_path().'/sess_'.session_id() i s le salveze n array-ul superglobal $_SESSION.

3.10.2

Authentication

A autentica pe cineva nu nseamn nimic mai mult dect a asocia un identicator unic (un ID) cu
un client (un browser), ID care va salvat n dou locuri: ntr-un cookie pe client, i pe server, de obicei
n numele ierului din interiorul directorului session_save_path().
Dei repet, in s subliniez nc o dat ct de fragil este aceast autenticare: un simplu string de
cteva zeci de caractere (session ID) face diferena dintre a autenticat sau nu ... sau a autenticat
ca altcineva.
Dac cineva reuete s fac rost de ID-ul unei sesiuni al unui alt utilizator, e ca i autenticat ca
acel utilizator.
29

Care n mod standard este PHPSESSID.

124

Dezvoltare web cu PHP

3.11. FELICITRI

i-ai putea imagina c a face rost de acest ID este ceva destul de complicat, i c nu oricine ar
putea face asta. Din fericire30 pentru noi, acest lucru este relativ trivial n capitolul 5 vei vedea cum o
singur greeal banal i poate oferi atacatorului site-ului tu s injecteze cod HTML i Javascript care
s i trimit acest ID31 .
Pentru a face lucrurile mai dicile, o msur adiional ar putea identicarea i dup adresa IP
($_SERVER['REMOTE_ADDR']), ns acest lucru are un dezavantaj: dac i aduci bine aminte din capitolul
Reelistic, mai muli utilizatori care mpart accesul la Internet printr-un router au aceeai adres IP
public.
Fcnd autenticarea i32 dup adresa IP, aplicaia ta ar putea deveni confuz deoarece vede o
singur adres IP i mai multe ID-uri de sesiune.
Adresa IP i ID-ul unic din cookie nu sunt ns singurele elemente ce pot luate n considerare la
autenticarea unui utilizator. Majoritatea browserelor, numite i ageni, trimit un string la ecare cerere,
pe care l poi accesa prin $_SERVER['HTTP_USER_AGENT'].

O schem de autenticare ieit din comun**

Extinde remote le storage cu autenticare. Parola va acel <nume secret>, iar ecare nume
secret va avea un ier uploads/<nume secret>/users.csv ce va conine o list de usernames. La
crearea unui nou <nume secret>, proces numit nregistrare pe site-urile pe care le cunoti deja, userul
va trebui s uploadeze acel ier users.csv. Nu vor exista drepturi de acces, deci toat lumea va putea
interzice accesul tuturor celorlali de ndat ce are credentials n users.csv.

Remote le storage cu galerie de imagini

Extinde aplicaia de la exerciiul anterior astfel nct s detecteze dac un <nume secret> are doar
imagini n el, i dac da, s aeze acel director ca pe o galerie de imagini.

Guestbook I**

Creaz un guestbook simplu, cu autenticarea unui singur administrator. Intrrile din guestbook
trebuiesc salvate (serializate) ntr-un format la alegere (json, csv, sau un format propriu), dar nu trebuie
s e HTML.
Utilizatorii care vor s lase un mesaj vor introduce nume, adres e-mail, un URL opional i mesajul
care poate conine doar tagurile HTML: <b>, <i>, <p>.
Adiional, o linie goal poate delimita paragrafe.
Creaz i o interfa de administrare, sistemul va avea un singur utilizator: administratorul. Prin
interfaa de administrare acesta va putea terge sau edita intrrile din guestbook sau bana adrese IP.

Felicitri
n aceste capitole ai nvat s lucrezi cu conceptele fundamentale din programare. Pe baza noiunilor
de reelistic ai putut nelege diferii vectori de atac, cum s i protejezi aplicaiile mpotriva lor, cum poi
30

din fericire deoarece este nc un motiv n plus s acordm o atenie deosebit securitii aplicaiilor noastre
Atacul se numete XSS - cross-site scripting
32
nu doar, ci i, conjunctiv: att dup sesiune, ct i dup IP
31

125

Dezvoltare web cu PHP

3.11. FELICITRI

autentica i autoriza utilizatorii, i multe alte posibiliti prin intermediul funciilor puse la dispoziie
de PHP.
Ai nvat i cum i poi modulariza codul astfel nct componente precum business logic, view logic
sau congurarea s e reutilizabile, eventual pe baza unor funcii proprii, care ar trebui s e la rndul
lor la fel de reutilizabile.
Pentru a concepe toate aceste lucruri, ai nvat i cum s inventezi structuri de date abstracte, pe
care toate aceste lucruri33 pot opera colectiv.

Recapitulare i sintez

Citete cu atenie sinteza de mai sus, apoi nchide cartea i scrie o sintez mai detaliat despre ce ai
nvat n propriile cuvinte, de cel puin 300 de cuvinte.
Mult mai important dect corectitudinea tehnic a rezumatului este capacitatea ta de a jongla cu
noiunile, chiar i cu riscul de a grei, deci nu te si s faci armaii ndrznee.

33

business logic, view logic, funciile PHP i funciile proprii

126

Capitolul

Baze de date i lucrul n echip


n acest capitol vei nva fundamentele bazelor de date i lucrul ntr-o echip de programatori, cu
toate uneltele necesare i unele soft skills de care are nevoie un programator.
Scopul acestui capitol este s te pregteasc pentru exerciiul de la sfritul capitolului care const
ntr-un proiect pe care l vei face ntr-o echip. ncepnd cu acest capitol, tutorii phpro mai mult te vor
ndruma, te vor consilia, att pe tine individual, doar atunci cnd ai absolut nevoie, dar mai ales pe
ntreaga echip.
Prin urmare, vei mult mai independent, dar vei i avea o responsabilitate mai mare cel puin fa
de colegii de echip.

Git
4.1.1 Istoria unui proiect
Probabil c pn acum te-ai confruntat deja cu urmtorul scenariu: vrei s testezi ceva n programul
tu, dar nu eti sigur c schimbarea va deveni permanent.
Cel mai probabil te-ai folosit de comentarii n astfel de cazuri: ai comentat o parte din codul surs i
ai scris o nou implementaie dedesubt. Dac a fost vorba de modicri prin mai multe iere, probabil
ai repetat acelai procedeu pentru ecare dintre acestea.
Dac ai avut noroc, schimbrile tale au fost bune, i tot ce a trebuit s faci n cele din urm a fost s
tergi implementaia veche, comentat, i s o lai doar pe cea nou n loc.
Dac nu ai avut noroc, i-ai dat seama c ideea ta nu a fost cea mai grozav, i a trebuit s restaurezi
versiunea veche. n urma restaurrii, probabil ai avut noroc i ai reuit s revii la versiunea veche fr
probleme.
ns cel mai probabil, nu ai avut noroc deloc.
Ei bine, mulumit unor programe numite revision control systems (abv. RCS), nu ai nevoie de noroc
atunci cnd codul surs al proiectului tu evolueaz, sau cnd doar vrei s testezi lucruri noi.
Cu un RCS, nu mai e nevoie s lai la voia ntmplrii modicrile aduse codului tot ceea ce faci
este nregistrat, ecare schimbare, e ea i ct de mic. Partea bun e c poi reveni la orice versiune a
codului, oricnd, oricum!
Dei ai multe avantaje atunci cnd foloseti un RCS ca un programator singur, RCS-urile i dezvolt
adevrata putere atunci cnd lucrezi n echip cu ali programatori.
Printre cele mai cunoscute RCS-uri se numr subversion, mercurial, bazaar, BitKeeper i git.
n acest curs, vei folosi Git. Git s-a nscut din necesitatea programatorilor kernelului Linux de a-i
controla mai organizat procesul de dezvoltare.

127

Dezvoltare web cu PHP

4.2. BAZE DE DATE RELAIONALE

Spre deosebire de subversion, cu git nu exist un server central, de aceea git se numete i DRCS, D
venind de la distributed.
Pentru o list a termenilor cei mai importani citete despre revision control.

4.1.2 Getting started


Sub GNU/Linux, instalarea este destul de simpl: folosete package manager-ul distribuiei tale
pentru a instala pachetul git.
Pentru Microsoft Windows, intr pe pagina ocial1 i instaleaz Full installer for ocial Git. La
pasul Adjusting your PATH environment, selecteaz Run Git from the windows command prompt. Restul
opiunilor ar trebui s e bune aa cum i le prezint installer-ul. Pe desktop ar trebui s-i apar simbolul
git bash.
Dup ce ai instalat git, urmeaz cartea ProGit2 , capitolele 1-3. Aceasta i va prezenta mai toate
noiunile elementare despre git.

A taste of git

Dac eti n programul de tutelare, ai deja cont pe github.com. Acest site i ofer hosting pentru
proiectele tale. Intr n contact cu noi pe IRC pentru a ndrumat.
Creaz un nou proiect pe github.com denumit la fel ca username-ul tu de pe github.com, iar apoi
cloneaz-l local i experimenteaz cu el.
Pentru lucrul cu repozitoriile hostate pe github, citete instruciunile de congurare de pe github3 .
ntreab-i pe ceilali cursani ce lucruri interesante mai poi face cu git.
ncearc s te joci ct mai mult cu acest utilitar, deoarece de acum ncolo toate proiectele tale vor
puse sub revision control n git.
i aminteti probabil i de gist-ul unde i-ai salvat toate soluiile la exerciii pn acum. Ei bine, un
gist nu este nimic altceva dect un repozitoriu git. l poi clona bine mersi, i opera pe el din confortul
consolei tale nu e nevoie s accesezi interfaa web pentru a posta ceva.
Creaz un fork al crii, f mici corecturi acolo unde vezi necesar, dac ai gsit greeli n carte, nva
s faci pull requests, s trimii patchuri, s deschizi issues pe interfaa web a proiectelor tale pus la
dispoziie de github.
Investete n jur de 40-80 de ore de lectur i de experimente pentru a deveni ct de ct rutinat n
folosirea acestor sisteme: git ca utilitar de sine stttor pe de o parte, i github.com ca hosting pentru
proiectele tale.

Baze de date relaionale


Bazele de date sunt folosite pentru a salva informaii structurate. Dup structura datelor, exist dou
cele mai rspndite forme de baze de date:
relaionale
orientate pe obiecte
Bazele de date relaionale (abv. RDBMS) se preteaz pentru informaii tabelare ce pot avea relaii ntre
ele. Cele orientate pe obiecte se preteaz pentru informaii arborescente gndete-te la arborescena
(i recursivitatea) unui document HTML.
n funcie de modul de acces, pentru ambele tipuri de mai sus exist iari dou categorii:
1

http://code.google.com/p/msysgit/
http://progit.org
3
http://help.github.com/
2

128

Dezvoltare web cu PHP

4.2. BAZE DE DATE RELAIONALE

de sine stttoare
dup arhitectura server-client
Pentru a folosi o baz de date de sine stttoare nu ai nevoie de un server. Baza de date const
ntr-un ier care conine toate datele i metadatele. Aceste baze de date pot trimise uor altcuiva i
nu este nevoie dect de un program care tie s opereze pe acea baz de date. Un exemplu consacrat
pentru astfel de baze de date este SQLite.
Bazele de date cu server-client au n mare trei componente:
ierul4 efectiv n care sunt salvate informaiile
daemonul care ateapt conexiuni de pe internet i deservete informaii din acele iere
clientul care se conecteaz la server i cere informaii
Atunci cnd clientul cere informaii de la un server, clientul nu primete toate informaiile, pentru
a-i putea alege ce vrea. Clientul trimite o cerere ntr-un limbaj special, cerere pe baza creia serverul
genereaz un rspuns care conine deja informaiile dorite de client.
Dei nu este relevant pentru folosirea bazelor de date, e important s claricm cum funcioneaz
aceste componente, i vom ncerca s o facem pe baza cunotinelor pe care le avem deja despre protocolul
HTTP i programele care l folosesc.
Clientul DB se conecteaz la serverul DB printr-un protocol de transfer al informaiilor precum
TCP/IP, similar cu felul n care i un browser se conecteaz la un daemon HTTP.
Transferul de informaii efectiv se face ntr-un limbaj neles de aceste dou programe un protocol
din nou: analog cu HTTP.
Una dintre diferenele cruciale este ns c acest client nu se conecteaz, trimite o cerere, primete
un rspuns, i apoi se deconecteaz. Nu. Acest lucru se ntmpl n cazul protocoalelor stateless precum
HTTP. DBMS-urile n schimb au de obicei protocoale stateful, adic se conecteaz la daemon, i aceasta
este meninut pn la ntreruperea ei explicit.
Odat conectat, clientul e pregtit s trimit cereri formulate ntr-un limbaj specic. n cazul
RDBMS-urilor, predominant este limbajul SQL (en. Structural Query Language , citit sikwl).
Aceast cerere formulat n limbajul SQL este apoi codat n protocolul specic DBMS-ului i trimis
acestuia. Faptul c ecare5 DBMS are un protocol specic este cauza imposibilitii comunicrii cu un
daemon de un tip folosind un client de alt tip6 n ciuda faptului c limbajul n care e formulat cererea,
SQL, este acelai7 .
n acest capitol vei folosi RDBMS-ul MySQL, deoarece este cel mai des folosit n conjuncie cu PHP.

Primii pai n baze de date


Partea I

Instaleaz-i daemonul i clientul MySQL. Sub Microsoft Windows poi descrca installerul de pe
site-ul ocial8 .

Partea II
Operaiile de baz se numesc create, retrieve, update, delete, de aici acronimul CRUD.
Acceseaz manualul MySQL9 i urmeaz capitolul Tutorial. Sub Windows te vei conecta la daemon
cu clientul mysql.exe.
4

n funcie de RDBMS i de ali factori, pot mai multe iere


aproape ecare
6
De exemplu, clientul mysql.exe nu poate comunica cu un daemon postgresql.
7
Exist i aici diferene ntre sisteme, dar limbajul n sinea lui este acelai, este standardizat.
8
Se numete MySQL Community Server i se gsete la adresa http://dev.mysql.com/.
9
http://dev.mysql.com/doc/
5

129

Dezvoltare web cu PHP

4.3. COMUNICAREA CU MYSQL DIN RUNTIME-UL PHP

Rezerv-i 40-80 de ore de lucru pentru a nva s faci operaii CRUD.

Comunicarea cu MySQL din runtime-ul PHP


n acest moment tii s faci operaii pe baze de date MySQL n limbajul SQL. De ndat ce ai o cerere
SQL care funcioneaz direct n clientul MySQL, aceasta poate trimis aa cum este ctre server, iar
rspunsul poate procesat.
Pentru a comunica cu daemonul MySQL, folosim extensia mysqli.
Listing 4.1: Cereri SQL statice
1
2
3
4
5

<?php
$connection = require_once 'dbconn .php ';
if( $connection ){
$result = mysqli_query ( $connection ,'SHOWDATABASES ');
$databases = mysqli_fetch_all ($result , MYSQLI_ASSOC );

6
7

var_dump ( $databases );

8
9
10

mysqli_close ( $connection );
}

.
n exemplul 4.1 poi vedea cum ne conectm la baza de date i cum trimitem o cerere SQL i prelum
rezultatele generate de acea cerere.
Pentru conectare am folosit un ier dbconn.php.
Listing 4.2: dbconn.php
1
2

<?php
return mysqli_connect ('localhost ','username ','password ','dbase ');

Metadatele dicionarelor returnate (aici probabil doar Database) sunt exact numele coloanelor cum
le-ai vzut dac ai folosit clientul mysql din linia de comand.
n general, n PHP, vei dori s generezi dinamic, programatic, stringul care conine cererea SQL.
Acest lucru se face de obicei pe baza inputului provenit direct sau indirect de la utilizator.
De exemplu, am putea avea
1

$SQL='SELECT *FROM`products ` WHERE `name `LIKE"%'. $name .'%"';

unde variabila $name are o valoare pus la dispoziie de utilizator. Stringul $SQL ar putea trimis
apoi daemonului cu aceeai funcie mysqli_query().
Putem spune c astfel am parametrizat cererea SQL cu variabila $name.
Dac ai o greeal n cererea generat, atunci poi confruntat cu dou tipuri de probleme: e cererea
n sinea sa este corect din punct de vedere sintactic, ns MySQL i returneaz o eroare, e modul n
care ai generat cererea este greit.
n primul caz, problema i rezolvarea sa nu in de PHP, ci de MySQL. Exemplul unei astfel de situaii
poate atunci cnd ncerci s selectezi elemente dintr-un tabel inexistent.
n al doilea caz, problema ine de codul PHP pe care l-ai scris pentru a genera acea cerere.
De obicei i poi da seama cu ce fel de problem te confruni uitndu-te la eroarea generat de mysqli,
folosind funcia mysqli_error().
Pn acum am construit cererile SQL integrnd valorile concrete - de exemplu valoarea variabilei
$name - n cererea SQL. MySQLi permite ns separarea cererii efective de datele care parametrizeaz
cererea SQL. Acest lucru se face folosind prepared statements.

130

Dezvoltare web cu PHP

4.4. DESIGNUL BAZELOR DE DATE


Listing 4.3: MySQLi Prepared Statements

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

<?php
$connection = require_once 'dbconn .php ';
if( $connection ){
$stmt = mysqli_stmt_init ( $connection );
if( mysqli_stmt_prepare ($stmt ,'SELECT `name `FROM`places ` WHERE `place_id `=? ')){
$place_id =3;
$name =NULL;
mysqli_stmt_bind_param ($stmt ,'i', $place_id );
mysqli_stmt_bind_result ($stmt , $name );
mysqli_stmt_execute ( $stmt );
while ( mysqli_stmt_fetch ( $stmt )){
var_dump ( $name );
}
$place_id =2;
mysqli_stmt_execute ( $stmt );
while ( mysqli_stmt_fetch ( $stmt )){
var_dump ( $name );
}
}
}

.
Semnele de ntrebare din cererea SQL sunt legate (en.
bounded) de variabile cu funcia
mysqli_stmt_bind_param(), iar cererea rezultat este executat apoi.
Prepared statements ne ofer o securitate mai bun, dar i exibilitate: poi reutiliza acelai statement,
ind nevoie doar s schimbi valoarea variabilei, i s execui din nou aceeai secven de cod. Astfel nu
mai este nevoie de regenerarea de la zero a cererii SQL, dup cum vezi pe liniile 14-18 din listingul 4.3.
Ca programatori PHP, am tentai s facem mai multe operaii de ct sunt necesare n PHP. Greit.
Ar trebui s facem toate operaiile ce in de criterii de cutare, sortri, ordonri, grupri, folosind SQL.
Sistemele de baze de date sunt optimizate pentru aceste operaii, i trebuie s protm de asta.
De asemenea, operaiile de baz trebuiesc i ele fcute tot n SQL, acolo unde este posibil. De exemplu,
suma preurilor produselor dintr-un co de cumprturi poate fcut folosind cereri precum
1

SELECT SUM(`price `)FROM`cart ` WHERE `customer_id `=42

n mod normal o astfel de cerere este mai rapid dect cererea ntregii liste de produse i calcularea
manual a sumei totale n PHP, ntr-o bucl. Asta bineneles numai dac nu aezi oricum lista de
produse, ci efectiv strict preul total.

Este important s ne gndim n ce contexte vor folosite cererile SQL pe care le crem, i n
funcie de asta s ne concepem cererile SQL.

Designul bazelor de date


Pentru a-i uura munca atunci cnd creezi baze de date, poi folosi o interfa grac pentru a
interaciona cu serverul. O astfel de aplicaie este phpMyAdmin. Aceasta este o aplicaie web scris n
PHP. Urmeaz paii din documentaia sa ocial pentru a o instala.
nainte de a te apuca de creat baze de date trebuie s te gndeti puin la structura informaiilor pe
care urmeaz s le salvezi n baza de date. in s subliniez: a informaiilor, care nu nseamn neaprat
a bazei de date.
S zicem c lucrm la o aplicaie pentru administrarea unei rme. Primul lucru de care avem nevoie
sunt angajai. Aceti angajai sunt oameni, deci au un nume, o zi de natere, o adres i un numr de
telefon.
Ca i concept, cam acestea sunt datele, ns trebuie s ne gndim i la cum vom dori s lucrm cu
aceste date.
131

Dezvoltare web cu PHP

4.4. DESIGNUL BAZELOR DE DATE

S zicem c rma noastr pune la dispoziie un mijloc de transport pentru a-i aduce pe angajaii si
la lucru. Teoretic avem adresa, ns va dicil s extragem informaiile din ea: avem nevoie de strad i
numr. n funcie de ele putem calcula apoi care sunt cele mai bune puncte de ntlnire, deoarece evident
acest mijloc de transport nu va putea trece pe la ecare acas, dac acea adres nu este n drum.
Concluzia logic e c ceea ce am numit adres trebuie mprit n dou cmpuri: strad i numr.
Acest fapt ne duce la principiul atomicitii datelor: ecare cmp trebuie s conin o singur informaie
indivizibil. Acelai principiu l putem aplica i numelui i numrului de telefon.
n exemplul nostru de mai sus, aceste coloane reprezint domenii. Dup cum observi, ecare domeniu
are un anumit tip de date, mai ales acum c am respectat principiul atomicitii: strada este un string,
iar numrul este un numr. Ba mai mult, este un numr pozitiv.
Este important s stabilim domeniile i tipul lor de date. Dac este vorba despre un domeniu pentru
numere, trebuie s stabilim exact intervalul de numere. Dac este vorba despre un string, atunci trebuie
s stabilim lungimea maxim, .a.m.d. n acest fel, chiar dac un domeniu apare n diferite tabele, toate
informaiile din baza de date vor consistente.
Un alt principiu este cel al evitrii redundanei. Redundana datelor nu este bun. Ce se ntmpl
dac primria oraului decide s redenumeasc o strad? Va trebui s redenumim toate rndurile din
tabelul nostru cu angajai care conin acea strad. n acest caz, redundana putea evitat uor dac
cream un nou tabel strzi n care puneam toate numele de strzi unice.
Tabelul cu angajai nu mai conine deci numele strzilor, care acum se a n acest nou tabel. Dar
cum facem legtura ntre un angajat i strada pe care locuiete? Pentru acest lucru avem la dispoziie
dou arme: foreign key i primary key.
Aceste keys sunt numere ntregi. Tabelul cu strzi ar trebui s aibe un PK unic numelui de strad
aferent. Teoretic, am putea folosi direct numele strzii, este un PK la fel de valid, deoarece acest nume
este oricum unic nu exist dou strzi cu acelai nume. ns practic, calculatoarele lucreaz mai uor
cu numere, care ntmpltor ocup i mai puin spaiu, deci baza de date ar deveni mai compact. Iar
deoarece calculatoarele lucreaz mai rapid cu numere, i cererile ar deveni mai rapide.
Deci adugm o nou coloan tabelului strzi numit ID, pe care o facem PK i pentru ca intrrile
din aceast coloan s e unice o facem AUTO_INCREMENT i i adugm UNIQUE.
Cum strzile au acum un PK, putem reveni la tabelul cu angajai i pune acolo n coloana strad
PK-ul strzii aferente din tabelul strzi. Spunem c aceast coloan este un FK i c refereniem datele
dintr-un alt tabel. Din acest motiv, bazele de date SQL se numesc baze de date relaionale.
ns bazele de date relaionale tiu mai multe. Misiunea unei baze de date nu este numai de a salva,
ordona, cuta sau grupa informaii, ci i de a ne garanta integritatea datelor. Ce se ntmpl dac tergem
din greeal (sau nu) o strad pe care nc locuiete un angajat? FK-ul acelui angajat va deveni invalid.
Cu baze de date putem asigura aceast integritate prin ceea ce numim referential integrity.
n MySQL, atunci cnd creezi tabelul care va trebui s tie despre integritate referenial, va trebui
s-i setezi ca ENGINE InnoDB.
Referenierea o vei crea pentru tabelul care face referenierea, deci n scenariul de mai sus pentru
tabelul angajai.

132

Dezvoltare web cu PHP

4.5. DEBUGGING AND PROFILING

Referential Integrity*

Creaz o baz de date cu integritate referenial, primary keys i foreign keys, ca n scenariul de
mai sus. Documenteaz mai nti domeniile folosite. Seteaz ca indeci coloanele dup care vei cuta n
cererile tale SQL (deci folosind SELECT).
Creaz cteva intrri n aceast baz de date i export-o n format SQL din phpMyAdmin.
Creaz cteva cereri SQL care demonstreaz integritatea referenial.

4.4.1 Database Normalization


Normalizarea bazelor de date10 este o categorisire formal i o extindere a principiilor expuse anterior
n designul bazelor de date.
Este sucient respectarea primelor trei forme normale n aplicaiile fr necesiti speciale.

Database Normalization***

Creaz o baz de date normalizat n 3rd NF cu cel puin 5 tabele. Creaz indeci unici i integritate
referenial dup necesitile domeniului aplicaiei pe care l descrii n mod relaional.
Introdu n toate tabelele date de testare.
Demonstreaz folosirea a 1-2 compound keys, e primary, e unique, e ambele.
Creaz cereri SQL mai complexe care implic operaiile JOIN, GROUP BY i HAVING - ultimele dou
ntr-un singur query. Descrie textual scenariile n care ecare dintre aceste cereri ar folosite ntr-o
aplicaie care ar face uz de aceast baz de date.

Debugging and proling


Pn acum, atunci cnd ai avut o problem, a trebuit s inspectezi uxul de execuie and __FILE__
i __LINE__, iar uxul de date and valorile variabilelor cu var_dump().
Dup ce ai terminat de inspectat ce se ntmpl n secvena de cod cu probleme, a trebuit s tergi
apelurile la funciile acestea de debugging.
Pentru a nu mai nevoie de aceste modicri, poi folosi un debugger. Unul din ele este xdebug i
poate adugat n PHP ca extensie.
Pentru a-l putea folosi uor, instaleaz-i i IDE-ul11 Netbeans, iar pentru a porni uor o nou sesiune
de debugging n refox, add-on-ul easy Xdebug12 .

Lucrul n echip
4.6.1 Norme de comunicare
4.6.2 Norme comportamentale

10

http://en.wikipedia.org/wiki/Database_normalization
http://en.wikipedia.org/wiki/Integrated_development_environment
12
https://addons.mozilla.org/en-US/firefox/addon/easy-xdebug/
11

133