PHP 1
PHP 1
org:
Manualul Programatorului
ver. 1.0 - Mai 2005
Programare.org: PHP – Manualul Programatorului 2
Prezentare
Acest e-book gratuit se adreseaza programatorilor sau tuturor celor care doresc
sa invete PHP, incepind cu nivelul introductiv, pentru incepatori, dar si lucruri mai
avansate. Toate notiunile vor fi introduse gradual si explicate. Nu este un
inlocuitor pentru documentatia PHP-ului care este o prezentare completa a
tuturor facilitatilor si functiilor limbajului, ci o metoda simpla si eficienta de a
prezenta posibilitatile limbajului la lucru, incepind cu pagini si exemple simple.
Unele materiale au fost luate din manualul oficial PHP, inclusiv cel in limba
romana. In unele situatii au fost adaugate tagurile de cod PHP in altele nu, insa e
clar ca este vorba despre cod PHP.
In acest e-book a fost lasat deoparte capitolul despre clase pentru ca ar trebui
abordat mai pe larg si nu intotdeauna e folosit pentru site-uri simple.
Despre Programare.org
Temele propuse pe site sint foarte variate: de la programare web, aplicatii sau
baze de date, pina la stiri din domeniul IT sau chiar discutii generale. Stim ca
exista si alte site-uri destinate programarii, insa unele sint specifice (PHP, VB,
etc.), iar altele nu au reusit sa adune suport si au disparut.
In aceeasi idee se inscrie noua serie de e-books despre programare mai ales
destinate incepatorilor, scrise in romaneste, simplu de inteles. Vizitati cit mai des
site-ul pentru noutati sau alte e-books care au fost publicate sau se vor publica
curind.
Multumim.
Programare.org: PHP – Manualul Programatorului 4
Cuprins
1. Istoria PHP
In 1997 PHP/LI a ajuns la versiunea 2.0 find rescris tot in C. Aproximativ 50.000
de site-uri au folosit acest limbaj, fiind un lucru deosebit, tinind cont ca a pornit ca
proiect personal.
Tot in 1997 s-a oprit dezvoltarea la PHP/LI si a aparut PHP 3.0 rescris de Andi
Gutmans si Zeev Suraski. Aceasta varianta seamana cu ceea ce stim noi din
PHP. Tot acum a fost redenumuit simplu PHP de la numele recursiv Hypertext
Preprocessor. Lansarea oficiala a PHP 3.0 a fost in iunie 1998.
Imediat dupa lansarea PHP 3.0 s-a inceput lucrul la urmatoarea versiune: 4.0.
Noua versiune a fost introdusa la mijlocul lui 1999 si a poarta numele de ‘Zend
Engine’ de la numele celor 2 creatori ai sai: Zeev si Andi.
2. Ce este PHP?
Dupa cum stiti HTML este un format static, care este salvat in fisiere apelate din
browsere pentru a fi vizualizate. Insa atunci cind se doreste crearea dinamica a
fisierului HTML trebuie folosit pe server un limbaj de scripting: PHP, Perl, ASP
sau altele. Din paginile respective se pot interoga baze de date, folosi informatii
din alte fisiere sau chiar de pe alte site-uri, folosi emailuri sau alte date stocate in
diverse modalitati, iar in final se construieste o pagina HTML pasata si vizualizata
in browser. PHP este transparent pentru vizitatori, ceea ce rezulta fiind HTML.
Nu exista compilare in PHP, codul raminid sub forma de sursa pe server fiind
interpretat la fiecare cerere. Se instaleaza librariile PHP-ului care stiu sa
functioneze cu serverul web oricare e acela, iar la cererea unui fisier cu extensia
.php (de obicei, pentru ca pot fi folosite si alte extensii) va fi chemat PHP-ul care
interpreteaza codul specific, dintre tagurile PHP-ului, rezultind HTML. Iar in
browserul clientului nu ajunge deloc cod PHP ci doar HTML. Asa ca parolele sau
codul dvs. ramine de nemodificat sau nevazut pe server. Principiul este la fel si
cu alte limbaje pentru Internet, server-side: ASP, Perl, ColdFusion, etc.
Codul PHP este marcat cu citeva taguri speciale. Cel mai adesea este folosit:
<?php … cod PHP … ?>
Codul PHP poate fi amestecat oriunde in pagina HTML, doar trebuie sa rezulte
cod HTML, cu structura unui document HTML.
De exemplu:
<html>
<head>
<title>Prima pagina</title>
<?php … cod PHP … ?>
</head>
<body>
Programare.org: PHP – Manualul Programatorului 7
De afisat ceva
<?php … cod PHP … ?>
</body>
</html>
/* acesta este un
comentariu multilinie */
Cum se pot scrie aceste lucruri? Cu orice editor HTML sau chiar plain-text. Multi
folosesc inclusiv Notepad sub Windows desi cu un editor specializat de HTML se
poate lucra mai eficient si mai rapid. Multi programatori web folosesc
Macromedia DreamWeaver, insa si alte editoare sint bune. Se poate folosi chiar
Zend Studio de la Zend.com, firma din spatele PHP-ului.
Programare.org: PHP – Manualul Programatorului 8
3. Instalare PHP
1. gzip -d httpd-2_0_NN.tar.gz
2. tar xvf httpd-2_0_NN.tar
3. gunzip php-NN.tar.gz
4. tar -xvf php-NN.tar
5. cd httpd-2_0_NN
6. ./configure --enable-so
7. make
8. make install
9. cd ../php-NN
10. ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql
11. make
12. make install
13. Setup your php.ini
cp php.ini-dist /usr/local/lib/php.ini
14. Edit your httpd.conf to load the PHP module.
For PHP 4:
LoadModule php4_module libexec/libphp4.so
For PHP 5:
LoadModule php5_module libexec/libphp5.so
15. AddType application/x-httpd-php .php .phtml
AddType application/x-httpd-php-source .phps
16. /usr/local/apache2/bin/apachectl start
Multi useri instaleaza PHP pe sistemele lor folosind Windows cu serverul de web
de la Microsoft: Internet Information Server (IIS). Procedura de instalare este
descrisa la http://php.net/manual/en/install.windows.iis.php .
Exista doua solutii pentru a rula scripturi PHP pe Microsoft Windows: folosind
ISAPI sau folosing CGI. Pentru prima varianta se folsoseste /sapi/php4isapi.dll
de adaugat in lista filtrelor ISAPI pe IIS din Internet Services Manager (Control
Panel -> Administrative Tools). Cealalta varianta este mai simpla si se foloseste
php.exe. Trebuie doar :
- copiat continutul arhivei PHP intr-un folder (c:\php)
- modificat php.ini si copiat in c:\Windows (sau c:\winnt)
- adaugat calea catre PHP in PATH (adaugati c:\php; in Control Panel -> System
-> Advanced -> Environment Variables -> System Variables (jos) -> Path)
Programare.org: PHP – Manualul Programatorului 9
- in Control Panel -> Administrative Tools -> Internet Services Manager click
dreapta pe Properties la numele computerului va deschide fereastra de mai jos:
Apoi deschideti Edit -> Home Directory -> Configuration unde dati click pe Add
pentru a defini o noua mapare cu Executable avind calea catre php.exe si
Extension = ”.php”.
Dupa asta in folderele IIS-ului (c:\inetpub\wwwroot sau in alte foldere setate sub
IIS) puteti folosi pagini PHP, pe linga ASP.
Doar aceasta linie simpla poate fi copiata intr-un fisier cu extensia .php (ex.
test.php), copiat in root-ul serverului web sau alt folder (c:\inetpub\wwwroot sub
IIS sau \htdocs sub Apache) si apoi chemat:
http://localhost/test.php
Bravo! Tocmai ati scris prima dvs. pagina PHP. Desigur continuare o sa puna
multe alte probleme intilnite in viata reala. Cu acest fel de pagina simpla puteti
testa daca ceva functioneaza bine, daca aveti un modul instalat sau nu si alte
lucruri utile.
Programare.org: PHP – Manualul Programatorului 11
<html>
<head>
<title>Prima pagina</title>
<?php echo “<!-- comentariu scris din PHP -->”; ?>
</head>
<body>
De afisat ceva
<?php print(“<hr>\nLinia a 2-a”); ?>
</body>
</html>
Apoi chema:
Dupa incarcarea paginii in browser incercati din meniul browserului View ->
Source pentru viazualizarea sursei HTML a paginii. O sa vedeti doar cod HTML,
nici urma de PHP. Asa cum am spus, PHP-ul doar se executa pe server si ceea
ce rezulta este HTML simplu.
Dupa cum se vede toate instructiunile se termina cu ‘;’ (punct si virgula). Spatiile
albe nu conteaza, iar o instructiune poate continua pe mai multe rinduri din
moment ce o sa fie terminata cu ‘;’.
<?php
echo phpversion();
echo date(“r”);
echo rand(); ?>
Dupa cum vedeti trebuie sa includeti cod HTML pentru ceva inteligibil, altfel totul
o sa fie bagat unul in altul. De exemplu am putea avea:
<?php
echo “Versiunea PHP: “.phpversion().”<br>\n”.
“Data curenta: “ . date(“r”).”<br>\n”;
echo “Numar aleator: “.rand(); ?>
Asta o sa afiseze:
Se poate vedea aici cum se pot folosi stringuri si concatena acestea. Si se poate
vedea instructiune pe 2 linii.
Programare.org: PHP – Manualul Programatorului 13
5. Variabile predefinite
Exista citeva variabile globale de tip siruri asociative disponibile in toate paginile.
Acestea sint: $_SERVER, $_GET, $_POST, $_SESSION, $_COOKIE,
$GLOBALS, $_FILE, $_ENV si $_REQUEST.
Dupa cum se poate vedea variabilele in PHP sint precedate de ‘$’. O sa vedem
in capitolul urmator mai multe lucruri despre variabilile obisnuite.
<?php
$var=1;
echo $var."<br>\n";
echo $GLOBALS['var']."<br>\n";
echo $GLOBALS[0]."<br>\n"; ?>
Ceea ce va afisa:
1
1
PHP Notice: Undefined offset: 0 in xxxx on line yy
‘PHP_SELF'
Adresa relativa a paginii curente (in care e folosit). De exemplu
$_SERVER['PHP_SELF'] in pagina http://example.com/test.php/foo.bar va
returna /test.php/foo.bar.
'SERVER_NAME'
Numele hostingului sau serverului daca e disponibil.
'SERVER_SOFTWARE'
Server identification string, given in the headers when responding to
requests.
'SERVER_PROTOCOL'
Numele protocolului folosit. De obicei este 'HTTP/1.0' sau 'HTTP/1.1';
'REQUEST_METHOD'
Programare.org: PHP – Manualul Programatorului 14
'SERVER_PORT'
Portul folosit de server. De obicei 80.
'PATH_TRANSLATED'
Calea absoluta pe server la fisierul executat, daca serverul permite.
'SCRIPT_NAME'
Numele paginii exeutate.
'REQUEST_URI'
Calea relativa de acces a paginii.
'PHP_AUTH_USER'
Numele userului daca pagina cere autentificare Apache.
'PHP_AUTH_PW'
Parola introdusa la autentificarea Apache.
<?php
echo $_SERVER['PHP_SELF']."<br>\n";
echo $_SERVER['HTTP_USER_AGENT']."<br>\n";
echo $_SERVER['REMOTE_ADDR']."<br>\n";
?>
/test3.php
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
192.168.123.1
$_SESSION este un alt sir disponibil global cu variabile care tin valori intre
diferite apeluri de pagini, pastrind valoarea lor pe toata durata vizitei unui site. O
sa intram mai tare in detalii mai tirziu despre sesiune si functiile necesare pentru
pornirea sau oprirea unei sesiuni. Folosirea variabilelor pastrate in $_SESSION
este foarte simpla:
$_SESSION[‘var’]=1;
echo $_SESSION[‘var’];
Insa sint si alte detalii despre sesiune care vor fi prezentate dupa introducerea
altor notiuni, intr-un capitol separat.
$_COOKIE pastreaza sau seteaza valori ale unor variabile pe calculatorul client
in fisiere mici permanente sau doar pe durata cit e deschis browserul. Aceste
valori sint pasate in mod invizibil in headerul (antetul) cererilor catre server sau
ale raspunsurilor si pot contine orice valori doriti. Se poate specifica un timp cit
cookie-ul este pastrat pe calculator, insa trebuie tinut cont si de faptul ca aceste
informatii pot fi sterse. Vom da si alte informatii despre cookies mai tirziu.
Programare.org: PHP – Manualul Programatorului 16
De exemplu:
<?php
$_COOKIE['x'] =555;
setcookie("xx",333);
print_r($_COOKIE); ?>
Va afisa:
Am introdus aici o noua functie: print_r() care afiseaza (de obicei pentru debug)
toate valorile unui sir cu tot cu indecsii numerici sau cheile de tip string.
$_FILE este un sir folosit pentru upload de fisiere. Are citeva chei predefinite cu
care se apeleaza parametrii fisierelor uploadate (nume temporar, marime, etc.).
Voi da mai tirziu citeva exemple de folosire.
Am lasat la urma cele mai des folosite variabile predefinite: $_GET si $_POST.
Cu acestia puteti avea valorile parametrii pasati paginii atit in adresa de chemare
a paginii (URL) cind este folosit HTTP GET, cit si in valori pasate de obicei din
forme HTML prin HTTP POST. De exemplu o sa vedeti des:
http://server.com/pagina.php?param1=1¶m2=2
Pentru a obtine valorile din ‘param1’ si ‘param2’ respectiv ‘1’ si ‘2’ o sa putem
scrie $_GET[‘param1’] sau $_GET[‘param2’]. De exemplu:
Va afisa: 1 - 2
<html><body>
<?php echo “var1=”.$_POST[‘var1’].”<br>var2=”.$_POST[‘var2’]; ?>
<form method=”post” action=”test4.php”>
<input type=”hidden” name=”var2” value=”abc”>
<input type=”text” name=”var1”>
<input type=”submit” name=”submit” value=”Apasa”>
</form>
</body></html>
Programare.org: PHP – Manualul Programatorului 17
Aici am dorit doar sa arat un exemplu simplu de folosire a tagului <form> din
HTML cu pasarea parametrilor folosind metoda POST (method=”post”) si de
preluare a valorilor pasate in codul PHP. Mai tirziu o sa intram in alte detalii
despre lucrul cu forme.
Toate aceste forme au cite o alternativa mai veche si mai rar folosita:
- $_SERVER se poate scrie si $HTTP_SERVER_VARS
- $_POST se poate scrie si $HTTP_POST_VARS
- $_GET se poate scrie si $HTTP_GET_VARS
- $_COOKIE se paote scrie si $HTTP_COOKIE_VARS
- $_FILES se poate scrie si $HTTP_POST_FILES
Exista totusi o diferenta intre noile forme si cele vechi: cele noi sint automat
globale si pot fi folosite peste tot, inclusiv in functii.
Asa cum am aratat deja orice nume de variabila incepe cu ‘$’. Este o conventie
PHP si este necesara intotdeauna. Variabilele nu se definesc si nu au un tip
propriu-zis (adica tipul este determinat in functie de valoarea tinuta si poate fi
schimbat). Se poate scrie direct:
$var1=1;
$var2=”un string”;
$var3=true;
$var1=$var1+1;
Nu sint valide nume de variabile care incep cu altceva decit litere sau ‘_’ (de
exemplu nu e valid $1a), nici cele care au diverse alte caractere (#,%, spatiu,
etc.). Sint lucruri de bun-simt la fel ca in alte limbaje.
Dupa declaratiile si initializarile de mai sus se poate schimba tipul ‘variabilei’, desi
nu e chiar un tip:
Exemple:
is_string($var1) => TRUE
is_integer($var1) => FALSE
Exista apoi citeva functii de lucru cu variabile pentru a testa valorile ei sau elibera
memoria variabilei:
- isset() si empty() verifica existenta unei variabile
- unset() – elibereaza datele variabilelor.
Exemplu de eliberare a unei variabile pentru a anu ajunge sa fie folosita mai tirziu
in alta parte a paginii (eventual chiar de hackeri):
unset($var1);
Se poate apoi obtine tipul unei variabile, dar si seta cu ajutorul functiilor gettype()
si settype(). Valorile acceptate sint:
• "boolean" (sau, până la PHP 4.2.0, "bool")
Programare.org: PHP – Manualul Programatorului 19
De exemplu:
$var1=1;
echo gettype($var1);
settype($var1,float);
define(“CONSTANTA1”,1);
define(“EROARE”,”A aparut o eroare!”);
$var1=CONSTANTA1+10;
echo EROARE;
Pentru constante exista functia constant() care returneaza valoarea ei, adica
echo EROARE;
echo constant(“EROARE”);
sint perfect la fel. Deci inutila a 2-a varianta, aproape intotdeauna, decit daca
numele constantei este generat dinamic:
$i=1;
echo constant(“CONSTANTA”.$i) ;
• Matematici: +, -, *, /, % (modulo)
Exemple:
$a = $b + $c;
echo $a*10;
• Atribuire: =
Exemple:
$a=3;
Programare.org: PHP – Manualul Programatorului 20
• Pe biti: & (AND), | (OR), ^ (XOR), ~ (NOT), << (rotire la stinga), >> (rotire
la dreapta)
Exemple:
$a = $a | $b;
$x = $y ^ 8;
$b = $b << 1;
• De comparatie: >, <, <=, >=, == (egalitate), === (identitate), <> (sau !=),
!== (ne-identic).
Exemple:
$a > $b, $a <> $b sau $a!= $b,
$a === $b; // $a este egal cu $b si au acelasi tip
• Controlul erorilor: @
Nu raporteaza erorile in instructiunea folosita, oricare ar fi aceste erori. Se
foloseste pentru a sari peste mesajele de erorare standard si testarea
valorilor returnate dupa terminarea instructiunii, eventual cu afisarea unui
mesaj de eroare dat de programator.
Exemplu: @$a=10/@b; // nu afiseaza “PHP Warning: Division by zero”
Sint unii operatori care se refera la notiuni ne-explicate inca aici (siruri sau
stringuri), insa cred ca sint lucruri simple, usor de inteles. Pentru detalii vedeti si
capitolele referitoare la acestea.
Programare.org: PHP – Manualul Programatorului 21
7. Instructiuni PHP
La fel ca multe alte limbaje si PHP are citeva instructiuni Acestea sint: if – else –
elseif, while, do..while, for, foreach, break, continue, switch, return, require(),
include(), require_once(), include_once(). Sa le vedem pe rind.
if – else – elseif
Testeaza conditia data si in functie de asta continua cu o ramura a instructiunii
sau cu alta, daca exista alternativa. Altfel nu executa nimic.
Exemple:
if($a>1) echo “var. a mai mare decit 1”; // este afisat doar daca $a>1
if($a>1) {
echo “var. a mai mare decit 1”;
$a=1;} //exemplu de instructiune compusa, folosind { } pentru grupare
if($a>1):
echo “var. a mai mare decit 1”;
endif;
while
Forma ei este
while (conditie) instructiune;
Sau poate fi
while (conditie): instructiune; endwhile;
Programare.org: PHP – Manualul Programatorului 22
$i=0;
while($i<5)
{echo ++$i.” “;}
Va afisa: 1 2 3 4 5
do … while
Este foarte asemanatoare cu while doar ca o sa avem conditia de testat la
sfirsitul ciclului. Ciclul se termina cind conditia nu mai este adevarata:
$i = 0;
do {
echo $i;
} while ($i > 0); // va parcurge ciclul doar o data
for()
Forma instructiunii este:
for(initializare;conditie;incrementare) instructiune;
foreach()
Aceasta instructiune este asemanatoare cu for() doar ca parcurge siruri. Are 2
forme diferite:
foreach( sir as $variabila) instructiune;
foreach( sir as cheie => $variabila) instructiune;
Cu prima se poate accesa doar valoarea unui element (in $variabila), iar cu a
doua se poate accesa atit cheia cit si valoarea unui element (in $cheie, respectiv
$variabila).
Exemplu:
$a=array(1,2,3);
foreach($a as $val) echo $val.” “;
foreach($a as $cheie => $val) {
echo “\n<br>cheia: “.$cheie.” – valoare: ”.$val”; }
break
Termina executia la una din instructiunile for, foreach while, do..while sau switch.
Exemplu:
Programare.org: PHP – Manualul Programatorului 23
Dupa cum vedeti conditia de oprire in for() lipseste insa este testat in corpul
instructiuni. Odata ce $i > 10 o sa termine ciclarea datorita instructiunii break.
continue
Aceasta instructiune este folosita in instructiunile repetitive si diferita fata de
break deoarece sare peste partea ramasa din ciclu la urmatorul element.
De exemplu:
switch
Instructiunea switch combina mai multe ramuri ale instructiunii if-elseif-else intr-o
singura instructiune, folosita pentru selectia unor valori dintre mai multe optiuni:
switch ($i) {
case 0:
echo "i este 0";
break;
case 1:
echo "i este 1";
break;
case 2:
echo "i este 2";
break;
default:
echo "i nu este 0, 1 or 2";
}
vedeti switch are nevoie de break pentru terminarea unei ramuri cind conditia
este adevarata.
return
Este folosita in functii pentru intoarcerea controlului executiei programului cu sau
fara returnarea unei valori. O vom vedea in detalii la capitolul functii.
include() si require()
Amindoua instructiunile include fisiere externe in cadrul paginii curente. La
intinirea lor fisierul specificat este inclus complet in locul instructiunii. Diferenta
intre ele este faptul ca dac afisierul de inclus lipseste sau da eroare include() va
da o avertizare, iar require() opreste executia paginii cu ‘fatal error’.
Exemple:
include 'file.php';
include 'http://www.example.com/file.php?foo=1&bar=2';
require ‘file2.php’;
require(‘file3.php’);
Dupa cum se poate observa se pot include fisiere locale dar si chiar de pe
Internet, folosing protocolul HTTP, eventual chiar cu parametri. Parantezele se
pot folosi sau nu (sint optionale).
include_once() si require_once()
Diferenta intre acestea si cele anterioare este faptul ca orice includere se face o
singura data, chiar daca fisierul de inclus apare de mai multe ori, eventual chiar
in diverse fisiere incluse. Este utila pentru evitarea definirii de 2 sau mai multe ori
a aceleasi structuri, ceea ce duce la eroare.
<?php //config.php
define(“NRMAX”,10);
$pas=2;
?>
<?php // pagina.php
include ‘config.php’;
for($i=0;$i<NRMAX;$i=$i+$pas) echo $i.” “;
?>
8. Stringuri
Ultimul exemplu este cel numit heredoc, in care puteti include stringuri pe mai
multe rinduri. ‘EOD’ poate fi inlocuit cu orice altceva doriti, doar sa fie repetat la
sfirsitul stringului.
Pentru a obtine caracterul de la pozitia n dintr-un string puteti folosi $a[$n] sau
$a{$n}. In exemplul de mai sus $a[0] sau $a{0} va fi ‘u’ (indexul incepe de la 0).
La PHP puteti folosi intr-un string delimitat cu ghilimele (“) si nume de variabile
care vor fi inlocuite automat cu valoarea lor. De exemplu:
$a=”123”;
$b=” valoarea este: $a”; // va returna “valoarea este: 123”
Exista insa situatii cind se doreste afisarea unui alt string imediat concatenat la
variabila data. De exemplu mai sus “valoarea este: 123a”. Pentru asta nu se
poate scrie “valoarea este: $aa” pentru ca s-ar face inlocuirea cu variabila
inexistenta $aa. Pentru aceste cazuri se poate scrie:
Aceasta cred ca este varianta preferata pentru a inlocui valoarea unei variabile in
stringuri date, mai exact folosind “{ }” pentru delimitarea numelui variabilei, in
afara operatorului de concatenare: $b=' valoarea este: '.$a.'a';
De retinut ca acestea nu functioneaza cu delimitatori apostroafe (‘):
$a=(string)1;
$a=strval(1); // sint echivalente
$a=”1.2”
$i=intval($a);
$f=floatval($a);
Exista apoi o multitudine de functii care se aplica stringurilor. Dintre cele mai
folosite amintesc:
O sa dau aici un mic exemplu de pagina care foloseste unele din aceste functii:
<?php
$a="un string";
echo "\n<br>\$a='".$a."'".
"\n<br>Lungime: ".strlen($a).
"\n<br>Caractere mari: ".strtoupper($a).
"\n<br>Pozitia 'st': ".strpos($a,"st").
"\n<br>Inlocuieste 'n' si 't' cu '_': ".str_replace(array("n","t"),"_",$a).
"\n<br>Pozitia 'st': ".strpos($a,"st").
"\n<br>Impartit in sir de stringuri: ";
$ar=explode(" ",$a);
print_r($ar);
// Accesare substring cu {}
$string = 'abcdef';
Programare.org: PHP – Manualul Programatorului 28
Exemple:
<?php
$string = "April 15, 2003";
$pattern = "/(\w+) (\d+), (\d+)/i";
$replacement = "\$1 \$3";
echo preg_replace($pattern, $replacement, $string);// afiseaza ‘April 2003’
$replace = array ("", "", "\\1", "\"", "&", "<", ">", " ", chr(161), chr(162), chr(163),
chr(169), "chr(\\1)");
Despre lucrul cu stringuri se mai pot spune multe alte lucruri, insa o sa ma
restring la citeva din lucrurile de baza. Nu uitati sa consultati documentatia
limbajului pentru toti parametrii posibili ai acestor functii, eventual cu alte
exemple de lucru cu aceste functii.
Programare.org: PHP – Manualul Programatorului 30
9. Siruri
Un sir (array) este o colectie de valori avind acelasi tip, accesate cu ajutorul unei
variabile si a unui index. Exista mai multe feluri de a defini un sir. Cel mai
frecvent este creat folosind array():
$a=array(1,2,3);
$a = array(3=>1, 5=>2);
Va afisa:
Apoi se folosesc:
echo $a[‘unu’];
$a= array(“a”);
$a[]=”b”;
$a[]=”c”;
echo $a[2]; // va afisa “c”
print_r($a);
Va afisa:
bar - 1 - nou
Array ( [foo] => bar [10] => 1 [11] => nou )
Tot asa cum se pot adauga elemente la un sir se pot si sterge folosind unset():
unset($a[11]);
$a=array(array(1,2,3),array(4,5,6));
Numarul elementelor unui sir poate fi obtinut cu functia count(). Pentru exemplul
de mai sus:
Pentru a obtine toate elementele unui sir se poate folosi un ciclu for():
Va afisa:
a["sir"][0]=1
a["sir"][1]=2
a["sir"][2]=3
In codul de mai sus $key si $val pot fi folosite cu orice nume de variabile (nu
neaparat acestea).
$a=array(1,2,3);
foreach($a as $val) echo $val.” “;
foreach($a as $cheie => $val) {
echo “\n<br>cheia: “.$cheie.” – valoare: ”.$val”; }
<?php
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");
$c = $a + $b; // Reuniunea $a si $b
echo "<br>Reuniunea \$a si \$b: \n";
print_r($c);
Programare.org: PHP – Manualul Programatorului 33
$c = $b + $a; // Reuniunea $b si $a
echo "<br>Reuniunea \$b si \$a: \n";
print_r($c);
?>
Asta o sa afiseze
Reuniunea $a si $b: Array ( [a] => apple [b] => banana [c] => cherry )
Reuniunea $b si $a: Array ( [a] => pear [b] => strawberry [c] => cherry )
Exista apoi destul de multe functii referitoare la siruri (tablouri) multe care incep
cu ‘array_’ dar nu numai, si anume pentru intersectie, diferenta, reuniune,
extrage un element aleator, sortare, inversare, rotire, etc. O sa dau mai jos citeva
din ele:
<?php
$a=array(10,20,30);
$b=array(10 => "a",20 => "b", 30=>30);
print_r(array_values($b));
Dupa cum vedeti lucrul cu siruri (tablouri) in PHP nu este complicat, fiind mult
ajutat de existenta unor functii utile pentru diverse operatiuni. Trebuie doar sa
vedeti daca nu cumva ceea ce doriti sa faceti are sau nu o functie gata
implementata, care va scuteste de multa munca.
Programare.org: PHP – Manualul Programatorului 36
10. Functii
Urmatorul pas in lucrul cu PHP sint functiile. Pina acum am dat exemplu de multe
functii implementate de limbaj. Insa deseori sint folosite functii create de
programator care primesc sau nu diversi parametri, fac niste operatiuni si
returneaza sau nu un rezultat.
O functie are un nume, poate avea sau nu parametri si poate intoarce sau nu un
rezultat. Poate arata asa:
Unde:
- foo este numele functiei;
- $arg_1, $arg_2, …, $arg_n sint parametri;
- $retval este valoarea returnata
function foo ()
{
echo "Exemplu de functie.\n";
}
function foo($n) {
echo $n;
$n=10;
}
$i=5;
foo($i);
echo " - ".$i;
Programare.org: PHP – Manualul Programatorului 37
Aceasta va afisa: 5 - 5
In acest caz se spune ca transmiterea parametrilor functiei s-a facut prin valoare,
modul standard de transmitere in PHP. Exista insa si o alta solutie: transmiterea
prin referinta cind valoarea schimbata in corpul functiei este transmis in codul
apelant.
function foo(&$n) {
echo $n;
$n=10;
}
$i=5;
foo($i);
echo " - ".$i;
Va afisa: 5 – 10
Un alt lucru posibil pentru parametrii functiei este initializarea lor la declararea
functiei:
function foo($n=5) {
echo $n;
}
foo();
Asta va afisa: 5
chiar daca functia este apelata fara parametri curenti.
Singura restrictie atunci cind exista parametri de functie initalizati este ca acestia
trebuie sa fie grupati ca ultimii parametri dati, nu la inceputul listei de parametri.
De exemplu:
De exemplu:
function foo($m,$n=5) {
echo $m+$n;
}
foo(3);
echo " - ";
foo(3,6);
Va afisa: 8 - 9
Prima data este initializat doar $m cu valoarea 3, iar $n va avea valoarea default
(=5). Apoi se va apela cu valoarea 3 pentru $m si 6 pentru $n.
echo foo(5);
$i=foo(10);
Care va afisa: 6
Si va initializa variabila $i cu 11
<?php
function foo() { echo "In foo()<br />\n"; }
function echoit($string)
{ echo $string; }
$func = 'foo';
$func(); // cheama foo()
Programare.org: PHP – Manualul Programatorului 39
$func = 'bar';
$func('test'); // cheama bar() cu un parametru
$func = 'echoit';
$func('test'); // cheama echoit() cu un parametru
?>
Un alt lucru mai avansat in lucrurl cu functiiel este posibilitatea declararii functiilor
fara parametrii si accesarii parametrilor folositi la apelul functiei cu ajutorul
functiilor auxiliare func_num_args(),func_get_arg() si func_get_args():
<?php
function test() {
echo "Parametrii dati sint:<br>\n";
for($i=0;$i<func_num_args();$i++)
echo "param[".$i."]=".func_get_arg($i)."<br>\n";
}
test(3,2,1);
?>
Va afisa:
PHP se dovedeste foarte util cind se pune problema prelucrarii datelor pasate din
forme HTML. Nu o sa prezentam aici toate detalii despre controalele disponibile
in formele HTML, dar o sa incep cu o scura prezentare a celor mai folosite:
<html>
<head><title>Test 5</title></head>
<body>
<form name="form1" method="post" action="test5.php">
<p>Text: <input type="text" name="textfield"><br>
Text multilinie: <textarea name="textarea"></textarea><br>
Check-box: <input type="checkbox" name="checkbox" value="checkbox"><br>
Buton radio:
<input type="radio" name="radiobutton" value="optiune1">Optiune1
<input type="radio" name="radiobutton" value="optiune2">Optiune 2 <br>
Selectie: <select name="select">
<option value="1">Optiune 1</option>
<option value="2">Optiune 2</option>
</select><br>
<input type="submit" name="Submit" value="Submit">
<input name="Cancel" type="reset" value="Cancel">
</p>
</form>
</body>
</html>
Puteti introduce valori in cimpurile date, selecta optiuni si apoi apasa butonul
‘Submit’ insa veti vedea ca nu se intimpla nimic cu valorile selectate. Sau daca
apasati butonul ‘Cancel’ valorile sint sterse imediat, fara alte actiuni.
Nu se intimpla nimic pentru ca este necesar cod PHP pentru prelucrarea valorilor
transmise din forma. Asa cum am spus aceasta prelucrare nu se poate face
folosind HTML simplu ci doar cod executat pe server, gen PHP, ASP, Perl sau
altele.
<html>
<head><title>Test 5</title></head>
<body>
<?php
if(isset($_POST['Submit'])) {
echo "Text: {$_POST['textfield']}<br>\n".
"Text multilinie: {$_POST['textarea']}<br>\n".
"Check-box: ".
($_POST['checkbox']=="checkbox"?"selectat":"neselectat")."<br>\n".
"Buton radio: ".
($_POST['radiobutton']=="optiune1"?"Optiune 1":"Optiune 2")."<br>\n".
"Selectie: ".($_POST['select']=="1"?"Optiune 1":"Optiune 2")."<br>\n";
}
?>
<form name="form1" method="post" action="test5.php">
<p>Text: <input type="text" name="textfield"
value="<?php echo $_POST['textfield']; ?>"> <br>
Programare.org: PHP – Manualul Programatorului 42
Text multilinie:
<textarea name="textarea"><?php echo $_POST['textarea']; ?></textarea>
<br>Check-box:
<input type="checkbox" name="checkbox" value="checkbox"
<?php if($_POST['checkbox']=="checkbox") echo "checked"; ?>>
<br>Buton radio:
<input type="radio" name="radiobutton" value="optiune1" <?php
if($_POST['radiobutton']=="optiune1") echo "checked"; ?>>
Optiune1
<input type="radio" name="radiobutton" value="optiune2" <?php
if($_POST['radiobutton']=="optiune2") echo "checked"; ?>>
Optiune 2 <br>
Selectie: <select name="select">
<option value="1" <?php if($_POST['select']=="1") echo "selected";
?>>Optiune 1</option>
<option value="2" <?php if($_POST['select']=="2") echo "selected";
?>>Optiune 2</option>
</select><br>
<input type="submit" name="Submit" value="Submit">
<input name="Cancel" type="reset" id="Cancel" value="Cancel">
</p>
</form>
</body>
</html>
- intii este verificat daca pagina este reincarcata dupa postarea inapoi a
parametrilor verificind valoarea butonului ‘Submit’ cu isset(). La prima
incarcare acesta e stringul null.
- daca s-au pasat parametrii inapoi se face afisarea valorilor selectate
- apoi se face afisarea din nou a formei, de data aceasta afisind valorile
selectate dinainte. De regula, valorile pasate spre prelucrare inapoi in
pagina nu mai sint afisate automat. In acest caz am folosit de exemplu:
<input type="text" name=”textfield”
value="<?php echo $_POST['textfield']; ?>">
Dupa cum se poate vedea sint importante numele controalelor din forma care
sint folosite apoi la apelul valorilor pasate inapoi spre prelucrare, folosind
$_POST: $_POST[‘textfield’], $_POST[‘checkbox’], $_POST[‘select’].
controlul. Insa pentru aceste cazuri si forma este una speciala avind nevoie de
un parametru: enctype="multipart/form-data"
$_FILES['file']['name']
Numele fisierului original
$_FILES['file']['type']
Mime type pentru fisierul de uploadat. Exemplu "image/gif", “image/pjpeg”.
$_FILES['file']['size']
Marimea fisierului in bytes.
$_FILES['userfile']['tmp_name']
Numele temporar sub care e copiat pe server
$_FILES['file']['error']
Codul erorii asociat uploadul, daca sint erori
In acest caz s-a presupus ca avem un control file numit ‘file’. Daca aveam
<input type=file name=poza> se folosea $_FILES['poza']['name'], s.a.m.d.
<html>
<head><title>Test Upload</title></head>
<body>
<?php
if(isset($_POST['Submit'])) {
if(($_FILES['file']['size']<100000)&&($_FILES['file']['size']>0)) {
$filename=date("Ymdhi").".tmp";
move_uploaded_file($_FILES['file']['tmp_name'], $filename);
echo "<p>S-a uploadat: {$filename}
<br>Fisier original: {$_FILES['file']['name']}
<br>Marimea: {$_FILES['file']['size']}
<br>Tipul: {$_FILES['file']['type']}</p>\n";
}
}
?>
<form name="form1" method="post" action="testupload.php"
enctype="multipart/form-data">
<p>Fisier:
<input type="file" name="file">
<input type="submit" name="Submit" value="Submit">
</p>
</form>
</body>
</html>
Programare.org: PHP – Manualul Programatorului 45
Dupa cum vedeti puteti testa lungimea fisierelor sau puteti schimba numele
fisierelor (aici este generat automat din data curenta).
Aveti insa grija cum folositi aceste optiuni pentru a nu deschide brese de
securitate pe site-ul dvs. Este posibil ca cineva sa incerce sa uploadeze fisiere
PHP pe care apoi sa le execute, sau alte tipuri de fisiere (HTML, JavaScript, etc.)
Asa ca intotdeauna sa verificati tipul fisierelor si marimea lor pentru a nu avea
surprize.
Programare.org: PHP – Manualul Programatorului 46
Din PHP se pot deschide si apoi scrie sau citi fisiere, de regula aflate pe server
dar si de pe alte calculatoare sau site-uri. Pentru aceste operatiuni sint folosite
citeva functii: fopen(), fclose(), fwrite(), fread(), fgets(), file(), flush(), filesize() si
altele.
<?php
$handle = fopen("/home/rasmus/file.txt", "r");
$handle = fopen("/home/rasmus/file.gif", "wb");
$handle = fopen("http://www.example.com/", "r");
$handle = fopen("ftp://user:[email protected]/somefile.txt", "w");
?>
$filename = "/usr/local/something.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
$filename = "c:\\files\\somepic.gif";
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
Programare.org: PHP – Manualul Programatorului 47
Acelasi lucru se poate realiza mai simplu folosind file(), doar ca asta returneaza
un sir de stringuri pentru fiecare linie, nu un simplu string:
$contents= file('http://www.example.com/');
$contents= file(‘/usr/local/something.txt');
<?php
$filename = 'test.txt';
if (is_writable($filename)) {
if (!$handle = fopen($filename, 'a')) {
echo "Nu pot deschide fisierul ($filename)";
exit;
}
if (fwrite($handle, date("d/m/Y h:i")."\r\n") === FALSE) {
die("Nu poate scrie ($filename)");
}
fclose($handle);
print_r(file($filename));
} else {
echo "Fisierul $filename nu se poate scrie.";
}
?>
Aveti doar grija sa creati intii fisierul ‘test.txt’ in folderul curent (al paginii PHP).
Se pot urmari aici citeva lucruri:
Toate aceste operatiuni sint separat de includerea unor fisiere PHP sau de alta
natura in codul paginii (realizat cu include() sau require()). Multe din informatiile
scrise sau citite din fisiere pot fi pastrate permanent in baze de date, insa despre
acestea in capitolul urmator.
readdir()), verificare daca este fisier sau director (is_file() – is_dir()), existenta
unui fisier (file_exists()) si altele.
<?php
$dir = "./";
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo "fisier: $file : tip: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
?>
Exista multe alte operatiuni care se pot face cu fisiere, insa nu intram acum in
toate detaliile. Ne restringem aici la lucrurile esentiale, pentru a nu ne pierde in
detalii si complica prea mult explicatiile.
Programare.org: PHP – Manualul Programatorului 49
13. MySQL
In sfirsit am ajuns la capitolul cel mai interesant pentru multi: lucrurl cu baze de
date. Voi exemplifica aici doar lucru cu MySQL. Exista si alte posibilitati, cel mai
frecvent dupa MySQL fiind PostgreSQL (asemenator), dar si altele.
De cele mai multe ori MySQL este gestionat chiar din browser cu ajutorul
phpMyAdmin un script PHP pentru administrarea MySQL. Dar exista si alte
solutii sau chiar operatiuni din linia de comanda pe server. Se pot crea baze de
date, care au tabele cu cimpuri, si eventual indecsi. Nu voi intra in detalii despre
bazele de datele relationale as acum este MySQL, spun doar ca operatiunile
permise se pot face folosind SQL.
SQL este un limbaj simplu de interogare, modificaren sau stergere a datelor, dar
si de manipulare a structurii bazei de date. Exemple simple:
Sau asa cum am spus, cel putin pentru modificarile structurii bazelor de date se
MySQL poate folosi phpMyAdmin (de la http://www.phpMyAdmin.net/ ) care mai
mult ca sigur il aveti instalat pe hostingul site-ului dvs.
Insa toate aceste se pot executa si cu ajutorul comenzilor PHP, care are functii
speciale pentru lucrul cu MySQL. Pasii care se executa deseori sint: conectarea
la baza de date folosind un user name si parola, deschiderea unei baze de date
(pot fi mai multe), interogarea SQL, eliberarea elementelor extrase din tabele,
incliderea conexiunii:
<?php
/* Conectarea si selectarea bazei de date */
$link = mysql_connect("mysql_host", "mysql_user", "mysql_password")
or die("Conectarea a esuat : " . mysql_error());
echo "Conectare cu succes";
mysql_select_db("my_database") or die("Nu se poate selecta baza de date");
echo "\t\t<td>$col_value</td>\n";
}
echo "\t</tr>\n";
}
echo "</table>\n";
/* Elibereaza inregistrarile */
mysql_free_result($result);
/* Inchide conexiunea */
mysql_close($link);
?>
Pentru acest caz se inlocuieste parametrii care reprezinta numele serverului (de
obicei “localhost”), numele si parola de acces, iar apoi numele bazei de date.
Daca se returneaza erorare la una din functiile de mai sus se afiseaza eroarea si
se opreste executia cu die(). Eroarea se obtine cu mysql_error().
$line = mysql_fetch_assoc($result);
echo $line[‘nume_cimp1’];
sau
$line = mysql_fetch_array($result);
echo $line[0];
- mysql_result() – returneaza valoarea unui cimp pe baza unei linii sau linii +
coloane
- mysql_fetch_object() – returneaza o linie ca obiect. Exemplu de folosire:
$row = mysql_fetch_object($result);
echo $row->nume_cimp;
- mysql_fetch_row() – obtine un o linie ca un sir
- mysql_unbuffered_query() - executa mai rapid comenzi SQL atunci cind
acestea nu returneaza inregistrari (UPDATE, DELETE, INSERT INTO, etc.)
<?php
if(!$link=mysql_connect('localhost', 'root', '')) {
die('Num se poate conecta'); }
$db_list = mysql_list_dbs($link);
while ($row = mysql_fetch_object($db_list)) {
echo "Baza de date: ".$row->Database . "\n";
$result = mysql_list_tables($row->Database);
while ($row_table = mysql_fetch_row($result)) {
echo " - Tabela: $row_table[0]\n";
}
mysql_free_result($result);
}
?>
Exista 2 loop-uri: una pentru toate bazele de date si alta pentru toate tabelele
unei baze de date. Am folosit 2 metode diferite de obtinere a unei linii din cele
returnate: mysql_fetch_row() si apoi mysql_fetch_object(). Se putea folosi doar
una, sau alta sau chiar mysql_fetch_assoc() sau mysql_fetch_array(). In acest
caz se conecteaza local cu userul default fara parola.
Alte pagini mai complicate cu PHP si MySQL sint o combinatie a tuturor acestor
lucruri, eventual chiar parametri pasati din forme HTML, lucru cu fisiere, includeri
de fisiere cu parametri globali (user name, parola, etc.) sau multe alte lucruri.
A. Sesiuni
De obicei paginile web sint ‘stateless’, adica fiecare cerere este tratata ca o
cerere noua fara sa se stie de cererile anterioare. In acest fel ar fi greu de
accesat un site dupa o identificare prealabila cu un nume de utilizator si parola
pentru ca valorile introduse s-ar pierde. Pentru evitarea acestor probleme
serverele web au modalitati de a tine minte vizitele ulterioare ale altor pagini, totul
fiind tratat ca o singura sesiune de lucru. Aceste sesiuni pot fi identificate (sa ai
acces abia dupa logare) si trebuie sa poata mentine diverse variabile pe toata
durata lor (exemplu: nume de utilizator, un id, parole ,etc.)
Aceste valori sint tinute $_SESSION si sint pastrate pe toata durata vizitei unui
site, chiar daca se incarca pagini diferite. Modalitatea tehnica de mentinerea
sesiunilor se face prin cookie sau parametri ascunsi sau vizibili in adresa paginii
cu un id unic, pasat inainte si inapoi la fiecare cerere .Atit timp cit id-ul e acelasi e
vorba de aceeasi sesiune.
Acest identificator este pastrat pe server si expira dupa un anumit timp. Este
generat aleator astfel incit s anu poata fi ghicit si se foloseste si al alte limbaje
server-side (ASP), nu doar PHP.
<?php
// testsession1.php
session_start();
echo 'Pagina #1';
$_SESSION['time'] = time();
echo '<br /><a href="testsession2.php?' . SID . '">pagina 2 cu sesiune</a>';
?>
Programare.org: PHP – Manualul Programatorului 54
<?php
// testsession2.php
session_start();
echo 'Pagina #2<br />
Tipul actual: '.date('Y m d H:i:s').
'<br />Timpul initial (din sesiune): '.date('Y m d H:i:s', $_SESSION['time']);
?>
Un lucru de recomandat pentru sesiuni este sa tineti cit mai putine informatii in
sesiune. De multe ori este destul un identificator. Toate informatiile sint pastrate
pe server iar pentru un site cu mii de vizitatori poate ocupa destula memorie.
B. Redirectari
Cea mai directa cale este folosind functia header(). Asta trimite parametri in
antetul paginii HTML trimisa in browser cu sepcificarea incarcarii altei pagini:
header(“Location: pagina_noua.php”);
header(“Location: http://alt_server.com/pagina_noua.php”);
Exista situatii cind veti obtine erorare la acesta redirectare pentru ca este
permisa doar in partea de inceput a paginii, inainte sa fie trimis corpul
raspunsului care browser (doar in anteteul raspunsului). Retineti s-o folositi la
inceputul paginii, nu in mijlocul ei.
Aceasta va reincarca pagina data dupa numarul de secunde dat (0 in acest caz),
automat, fara interventia userului.
Metoda folosing header() este utila cind totul se vrea sa se faca transparent
pentru vizitator, fara ca acesta sa-si dea seama ca a fost redirectata catre alta
pagina.
Metodele cu META Refresh sau JavaScript pot fi utile cind se doreste afisarea
unui mesaj scurt de redirectare, gen ‘asteptati putin pina se reincarca pagina’.
Incarcarea noii pagini poate dura citeva secunde timp cit va fi vizibil textul initial.
Programare.org: PHP – Manualul Programatorului 56
C. Sockets
Exista situatii cind este nevoie de un mai mare control de conectare un unor
servere folosind diverse protocoale. De exemplu chiar la alte servere web dar nu
numai. Pentru asta exista lucrul cu sockets folosind functia fsocketopen():
<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>
Aici intervin mai multe probleme. Conexiunea se poate face practic pe orice
calculator si pe orice port, atit timp cit conexiunile sint acceptate. Apoi insa
trebuie folosit in mod direct comenzile protocolului respectiv. In exemplul dat e
vorba de HTTP cu comanda GET, unde este ceruta o pagina si afisat raspunsul.
Trebuie vazut in mod concret detalii privind protocolul folosit, ce comenzi are si
ce parametri. Se poate folosi FTP, SMTP (emailuri), NNTP (servere de news),
WHOIS, dar si alte protocoale. Pentru unele din acestea sint alte functii
specializate, insa totul poate fi realizat si cu aceasta functie la nivel de jos.
Evident exista si alte module, acestea find dintre cele mai uzuale.
Parametrii existenti se pot modifica in php.ini. Insa trebuei facut diferenta intre un
parametru al unui modul existent sau lipsa modulului. De obicei daca va lipseste
un astfel de modul intrebati hostingul.
Programare.org: PHP – Manualul Programatorului 59
- nl2br() – inlocuieste caracterele de linie noua cu tagul HTML “<br>”. Este foarte
util pentru afisarea textelor multilinie in browser:
Exemplu: echo nl2br("text pe\n2 linii.");
Afiseaza:
text pe
2 linii.