php si mysql

22
. PHP si MySQL Introducere Exista in mod curent in limbajul PHP trei seturi de functii (sau clase) pentru lucrul cu MySQL. Aceste seturi de functii, mai sunt numite si extensii. Toate aceste extensii ajuta interogarea si administrarea unei baze de date MySQL prin intermediul PHP-ului. extensia mysql - este prima extensie folosita pentru lucrul cu MySQL din PHP, din acest motiv probabil este inca cea mai raspandita in scripturile deja dezvoltate. Extensia MySQL contine doar functii (interfata procedurala) nu si clase (interfata orientata pe obiect) si este recomandata doar pentru versiuni de MySQL mai vechi de 4.1.3. Elementele avansate de MySQL (prezente in versiuni ulterioare versiunii 4.1.3) nu sunt disponibile in aceasta extensie. Din acest motiv, aceasta extensie nu mai este dezvoltata in mod activ, iar echipa PHP recomanda folosirea celorlalte doua extensii (mysqli sau PDO) in locul acesteia. extensia mysqli - a urmat extensiei mysql si contine atat functii (interfata procedurala) cat si un set de clase (interfata orientata obiect) pentru operatiile uzuale cu MySQL. Aceasta extensie este mai avansata decat extensia mysql, (mysqli este prescurtarea de la mysql improved) si introduce noi facilitati prezente in versiunile peste MySQL 4.1.3 - lucrul cu tranzactii, interogari multiple, stored procedures, etc. extensia PDO (PHP Data Objects) este ceea ce se numeste o "database abstraction layer"; Adica, PDO contine o interfata orientata obiect (set de clase si metode) pentru lucrul in mod unitar cu o bazele de date din PHP. Concret, metodele folosite cu PDO sunt aceleasi fie ca folosim o baza de date MySQL, Oracle, Firebird, PostgreSQL, etc. Deci, putem schimba sistemul de baze de date pentru aplicatia noastra (bineinteles cu una din bazele de date suportate de aceasta extensie), fara sa schimbam codul PHP, sau cu schimbari minore. Acelasi lucru nu se intampla cu extensiile mysql sau mysqli deoarece acestea contin functii specifice pentru lucrul cu MySQL. Dezavantajul principal al PDO este faptul ca nu se pot folosi cateva din facilitatile foarte specifice si avansate ale unui sistem de baze de date MySQL, sau alt DBMS. In acest curs se va prezenta in detaliu extensia mysql pentru ca este destul de raspandita si probabil cel mai simplu de folosit pentru inceput. Apoi insa, prezint extensia mysqli, diferentele ce apar fata de extensia mysql, iar in continuare in exemplele din curs se va lucra cu extensia mysqli, fiind cea recomandata si de echipa PHP.Trecerea de la mysql la mysqli este simpla, pentru ca cele doua extensii se aseamana destul de mult. Extensia mysql Conectarea la serverul MySQL Pentru a accesa o baza de date MySQL din PHP, scriptul nostru in PHP va indeplini rolul de client si se va conecta la un server MySQL pentru ca ulterior sa comunice cu acesta si sa-i trimita instructiuni sql. Conexiunea la serverul MySQL se face cu ajutorul functiei mysql_connect() si este pastrata intr-o variabila de tip resource, variabila returnata de mysql_connect().

Upload: roxana-sarbu

Post on 01-Jan-2016

42 views

Category:

Documents


0 download

DESCRIPTION

php and mysql basic

TRANSCRIPT

Page 1: Php Si Mysql

.PHP si MySQL

IntroducereExista in mod curent in limbajul PHP trei seturi de functii (sau clase) pentru lucrul cu MySQL. Aceste seturi de functii, mai sunt numite si extensii. Toate aceste extensii ajuta interogarea si administrarea unei baze de date MySQL prin intermediul PHP-ului.

extensia mysql - este prima extensie folosita pentru lucrul cu MySQL din PHP, din acest motiv probabil este inca cea mai raspandita in scripturile deja dezvoltate. Extensia MySQL contine doar functii (interfata procedurala) nu si clase (interfata orientata pe obiect) si este recomandata doar pentru versiuni de MySQL mai vechi de 4.1.3. Elementele avansate de MySQL (prezente in versiuni ulterioare versiunii 4.1.3) nu sunt disponibile in aceasta extensie. Din acest motiv, aceasta extensie nu mai este dezvoltata in mod activ, iar echipa PHP recomanda folosirea celorlalte doua extensii (mysqli sau PDO) in locul acesteia.

extensia mysqli - a urmat extensiei mysql si contine atat functii (interfata procedurala) cat si un set de clase (interfata orientata obiect) pentru operatiile uzuale cu MySQL. Aceasta extensie este mai avansata decat extensia mysql, (mysqli este prescurtarea de la mysql improved) si introduce noi facilitati prezente in versiunile peste MySQL 4.1.3 - lucrul cu tranzactii, interogari multiple, stored procedures, etc.

extensia PDO (PHP Data Objects) este ceea ce se numeste o "database abstraction layer"; Adica, PDO contine o interfata orientata obiect (set de clase si metode) pentru lucrul in mod unitar cu o bazele de date din PHP. Concret, metodele folosite cu PDO sunt aceleasi fie ca folosim o baza de date MySQL, Oracle, Firebird, PostgreSQL, etc. Deci, putem schimba sistemul de baze de date pentru aplicatia noastra (bineinteles cu una din bazele de date suportate de aceasta extensie), fara sa schimbam codul PHP, sau cu schimbari minore. Acelasi lucru nu se intampla cu extensiile mysql sau mysqli deoarece acestea contin functii specifice pentru lucrul cu MySQL. Dezavantajul principal al PDO este faptul ca nu se pot folosi cateva din facilitatile foarte specifice si avansate ale unui sistem de baze de date MySQL, sau alt DBMS.

In acest curs se va prezenta in detaliu extensia mysql pentru ca este destul de raspandita si probabil cel mai simplu de folosit pentru inceput. Apoi insa, prezint extensia mysqli, diferentele ce apar fata de extensia mysql, iar in continuare in exemplele din curs se va lucra cu extensia mysqli, fiind cea recomandata si de echipa PHP.Trecerea de la mysql la mysqli este simpla, pentru ca cele doua extensii se aseamana destul de mult.

Extensia mysqlConectarea la serverul MySQLPentru a accesa o baza de date MySQL din PHP, scriptul nostru in PHP va indeplini rolul de client si se va conecta la un server MySQL pentru ca ulterior sa comunice cu acesta si sa-i trimita instructiuni sql. Conexiunea la serverul MySQL se face cu ajutorul functiei mysql_connect() si este pastrata intr-o variabila de tip resource, variabila returnata de mysql_connect().

Aceasta variabila (denumita uneori $link) reprezinta conexiunea la baza de date si va fi folosita ulterior (implicit sau explicit) de alte functii mysql pentru a trimite instructiuni prin aceasta conexiune, stabilita la primul pas (conectarea la baza de date). Semnatura (putin simplificata) a functiei mysql_connect() este: Pseudocodresource mysql_connect (string $server, string $username, string $password [, bool $new_link= false] )

Pentru conectarea la un server MySQL avem deci nevoie de 3 parametri (informatii): $server - numele sau ip-ul serverului respectiv. In general, acesta va fi localhost. Cuvantul localhost

identifica intotdeauna calculatorul local, adica cel pe care se afla scriptul de la care ne conectam. Indiferent ca testam site-ul offline (la noi pe calculator) sau online (pe serverul de gazduire), localhost isi pastreaza semnificatia pentru ca este acelasi calculator cu cel pe care avem scriptul PHP. Insa, daca avem script-ul PHP pe un calculator, si serverul MySQL pe altul, putem specifica un nume de domeniu sau IP ca $server. In plus, optional, putem specifica si port-ul pe care ne conectam (Ex: www.mysite.ro:3307).

$username - accesul (privilegiile) la resursele unui server de baze de date este acordat pe baza utilizatorului ce se conecteaza la acel server. Cand lucrez local, probabil voi folosi utilizatorul cu drepturi depline, si anume: root. Online (pe serverul de gazduire) voi realiza un utilizator cu acces limitat si-l voi utiliza pe acela pentru conectarea din scripturile php.

$password - parola cu care se autentifica $usernameParametrul $new_link (de tip boolean) este implicit false. Daca il folosim si e true, fiecare nou apel al functiei mysql_connect() cu aceiasi parametri va deschide o noua conexiune catre baza de date in loc sa foloseasca conexiunea existenta. In cele mai multe cazuri nu avem nevoie de acest lucru.

conectare.php

Page 2: Php Si Mysql

123

<?phpmysql_connect('localhost', 'root', '') or die('Eroare la conectare !');?>

NotaSintaxa nume_functie() or die('Eroare...') sau $rezultat = nume_functie() or die('Eroare') este intalnita des in PHP iar explicatia este urmatoarea:

or este un operator logic, si ca toti operatorii logici actioneaza cu "scurt-circuitare"; adica, este evaluat operandul din stanga, si anume apelul nume_functie(). Daca acesta returneaza true, nu se va mai evalua die('Eroare'); pentru ca poate determina faptul ca rezultatul operatiei este true. Daca in schimb apelul functiei returneaza false (sau 0), atunci se evalueaza die('Eroare'), instructiune ce va opri executia script-ului curent, afisand mesajul: Eroare.

motivul pentru care se foloseste or si nu || este ca or are o prioritate mai mica fata de "=". Prin urmare, variabilei $rezultat ii va fi atribuit rezultatul apelului nume_functie() si apoi se va executa operatia logica or

Vezi si subcapitolul Operatori logiciSchimbati in script-ul de conectare parametrii de conectare la baza de date, pentru a testa diferitele erori.

Alte exemple de conectare (ce difera mai mult in stilul de lucru) sunt:

conectare2.php 123456789

10

<?php/*in cazul in care conectarea se face cu succes, conexiunea se pastreaza in variabila de tip resursa $link*/ $link = mysql_connect('localhost', 'root', '') or die('Eroare la conectare !'); // puteti verifica prezenta unei valori de tip resursa in variabila $link// var_dump($link);?>

In acest al 3-lea exemplu, tin informatiile de conectare la baza de date in variabile (recomandat), pe care le transmit apoi ca parametri functiei mysql_connect(). Folosesc operatorul @ ce are ca efect ignorarea mesajelor de eroare generate de o functie, astfel incat sa captez eroarea ulterior, cu ajutorul functiei mysql_error();

conectare3.php 123456789

101112

<?php$db_host = 'localhost';$db_user = 'root';$db_pass = ''; $link = @mysql_connect($db_host, $db_user, $db_pass);//var_dump($link); // pentru debug if (!$link) { die('Eroare la conectare: ' . mysql_error());}?>

Selectarea bazei de dateSemnatura functiei este: Pseudocodbool mysql_select_db ( string $database_name [, resource $link_identifier ] )Parametri:

$database_name - numele bazei de date pe care o selectam

Page 3: Php Si Mysql

$link_identifier - variabila ce reprezinta conexiunea la serverul de baze de date. Aceasta variabila este returnata de mysql_connect() si este de tipul resource. Pentru aceasta functie, acest parametru este optional... PHP-ul va folosi ultima conexiune deschisa

Daca nu se afiseaza nimic in browser, in urma exemplului de mai jos, inseamna ca totul e bine, a fost deschisa conexiunea la serverul MySQL si s-a selectat o baza de date.

conectare.php 123456789

1011121314

<?php$db_host = 'localhost';$db_user = 'root';$db_pass = ''; $link = @mysql_connect($db_host, $db_user, $db_pass); if (!$link) { die('Eroare la conectare: ' . mysql_error());} mysql_select_db('mysite') or die(mysql_error()); ?>

Executarea unei instructiuni sqlIn continuare, pentru a urmari exemplele ce folosesc instructiuni catre serverul de baze de date, trebuie sa includeti codul din conectare.php pentru a va putea conecta la baza de date si selecta o baza de date pe care lucrati. Acest lucru se poate face si cu copy-paste in fiecare script in care lucrati, dar e mai simplu sa includeti fisierul cu conectarea la baza de date cu ajutorul instructiunilor include sau require (vezi: include, require). Trimiterea unei instructiuni sql catre serverul MySQL se face cu ajutorul functiei mysql_query(), care are urmatorul prototip: Pseudocodresource mysql_query ( string $query [, resource $link_identifier ] )

$query - va fi instructiunea sql. Ex: 'SELECT * FROM utilizatori'. Se poate trimite o singura instructiune sql o data, si NU este urmata de punct si virgula.

$link_identifier - parametru optional ce reprezinta conexiunea catre serverul MySQL. Daca nu este specificata, se foloseste conexiunea curenta

Valoarea returnata de mysql_query()Valoarea returnata de mysql_query() depinde de tipul de instructiune sql folosita. Sa presupunem ca pastram valoarea returnata intr-o variabila numita $result. ($result = mysql_query(...)).

Se disting doua cazuri: 1. Instructiunea sql este de tipul - INSERT, UPDATE, DELETE, DROP. In acest caz, $result este true daca instructiunea s-a executat cu succes, sau false daca MySQL a intalnit o eroare in executarea instructiunii sql.

2. Instructiunea sql este de tipul - SELECT, sau alte instructiuni sql ce returneaza inregistrari. In acest caz, $result este o variabila de tip resource ce contine setul de inregistrari returnat de server in urma executarii instructiunii sql. In cazul in care s-a primit o eroare la executarea instructiunii sql , $result va fi false. Important este ca, in cazul unei instructiuni SELECT executata cu succes, valoarea returnata de mysql_query() (variabila $result in cazul nostru) va contine inregistrarile returnate in urma query-ului sql, inregistrari ce pot fi extrase din aceasta variabila cu ajutorul unor functii specializate: mysql_fetch_row(), mysql_fetch_assoc(), mysql_fetch_array(). Trebuie deci sa retinem ca datele din $result nu pot fi vizualizate altfel decat prin extragerea lor cu functiile de mai sus.Instructiuni de actualizare - insert, update, deleteNota

In faza de testarea sau constructie a unui script PHP ce trimite instructiuni catre un server MySQL, verificam dupa rularea scriptului cu un client MySQL (de exemplu phpMyAdmin) daca au fost inserate, actualizate sau sterse inregistrarile respective, realizand un SELECT (sau apasand butonul Browse) pe tabelul/tabelele respective.

Exemplu executare INSERT cu mysql_query():

Page 4: Php Si Mysql

123456789

<?phpinclude("conectare.php"); $sql = "INSERT INTO utilizatori (username, email, anNastere, sex, dataAdaugarii) VALUES ('dan', '[email protected]', 1981, 'm', now()) ";//echo $sql;mysql_query($sql) or die(mysql_error()); ?>

Referitor la exemplul de mai sus: instructiunea echo $sql; are doar rol de debug. Este foarte util de multe ori sa afisam in browser exact

instructiunea sql ce va fi executata cu PHP si eventual sa o copiem si sa o testam manual in phpMyAdmin. Mai ales cand aceasta instructiune va fi formata dinamic, cu ajutorul variabilelor, asa cum vom vedea mai tarziu.

instructiunea care trimite codul sql catre serverul MySQL este: mysql_query($sql). In caz ca aceasta esueaza, cu ajutorul functiei mysql_error() voi afisa eroarea returnata de serverul mysql. Functia die() va afisa eroarea si va opri executia scriptului.

valorile de tip string sau date din mysql, sunt scrise intre ghilimele. Ca sa nu inchidem string-ul deschis in php cu ghilimele duble, voi folosi pentru ghilimele simple in instructiunea sql. Se poate si invers.

in caz ca executati a doua oara acest exemplu, veti obtine o eroare gen: "Duplicate entry 'dan' for key 2"; datorita faptului ca avem un index unic pentru coloana username

Exemplu executare UPDATE cu mysql_query(): 12345678

<?phpinclude("conectare.php"); $sql = "UPDATE utilizatori SET email = '[email protected]' WHERE utilizatorId = 3";mysql_query($sql) or die(mysql_error()); echo 'Randuri afectate de query: ' . mysql_affected_rows();?>

Daca am nevoie sa stiu cate randuri au fost afectate de ultima instructiune insert, update sau delete pot folosi functia mysql_affected_rows() Astfel, daca rulez prima data exemplul respectiv (si inregistrarea e modificata), numarul returnat de mysql_affected_rows() este 1. Cand rulez exemplul ulterior, MySQL detecteaza faptul ca nu s-a modificat nici o inregistrare din tabel, iar mysql_affected_rows() va returna 0.

Exemplu executare DELETE cu mysql_query(): 12345678

<?php $sql = ' DELETE FROM utilizatori WHERE utilizatorId > 6';mysql_query($sql) or die(mysql_error()); echo 'Randuri sterse: ' . mysql_affected_rows(); ?>

Extragerea informatiilor - selectExecutarea cu mysql_query() a unei instructiuni de tip SELECT va returna o valoare de tip resource ce contine setul de date extras din baza de date. Setul de inregistrari aflate in variabila returnata de mysql_query() va fi extras cu ajutorul urmatoarelor functii:

array mysql_fetch_row ( resource $result ) - returneaza inregistrarea curenta sub forma unui tablou cu chei numerice, astfel: prima coloana din setul de rezultate va avea index-ul 0, a doua coloana 1, etc.

array mysql_fetch_assoc ( resource $result ) - returneaza inregistrarea curenta sub forma unui tablou asociativ - avand ca si chei, numele coloanelor din setul de inregistrari

Page 5: Php Si Mysql

array mysql_fetch_array ( resource $result [, int $result_type= MYSQL_BOTH ] ) - in mod implicit aceasta functie returneaza un tablou cu chei atat numerice cat si de tip string pentru valorile dintr-o inregistrare. Asta inseamna ca valorile campurilor unei inregistrari sunt duplicate in acest tablou, pentru a fi accesate folosind atat chei numerice cat si chei de tip string. Al doilea parametru (optional, implicit este constanta MYSQL_BOTH) poate fi constanta MYSQL_ASSOC caz in care aceasta functie este similara cu mysql_fetch_assoc(), sau poate fi constanta MYSQL_NUM, caz in care functia este similara cu mysql_fetch_row().

select.php 123456789

1011

<?phpinclude("conectare.php"); $sql = 'SELECT utilizatorId, username, email FROM utilizatori ORDER BY utilizatorId DESC LIMIT 3';$result = mysql_query($sql) or die(mysql_error()); while ($d = mysql_fetch_row($result)) { print_r($d); } ?>

In exemplul select.php inlocuiti functia mysql_fetch_row() cu mysql_fetch_assoc() si apoi cu mysql_fetch_array() si observati diferentele tabloului $d. Va reamintesc, pentru a observa mai bine afisarea unui tablou cu functia print_r() trebuie sa va uitati in sursa browser-ului, pentru a vedea fiecare element pe cate o linie. In functie si de inregistrarile pe care le aveti in tabel, veti obtine ceva similar cu:

mysql_fetch_row() mysql_fetch_assoc() mysql_fetch_array()

Array( [0] => 5 [1] => anamaria [2] => [email protected])Array( [0] => 4 [1] => vasile [2] => [email protected])Array( [0] => 3 [1] => ion [2] => [email protected])

Array( [utilizatorId] => 5 [username] => anamaria [email] => [email protected])Array( [utilizatorId] => 4 [username] => vasile [email] => [email protected])Array( [utilizatorId] => 3 [username] => ion [email] => [email protected])

Array( [0] => 5 [utilizatorId] => 5 [1] => anamaria [username] => anamaria [2] => [email protected] [email] => [email protected])Array( [0] => 4 [utilizatorId] => 4 [1] => vasile [username] => vasile [2] => [email protected] [email] => [email protected])Array( [0] => 3 [utilizatorId] => 3 [1] => ion [username] => ion [2] => [email protected] [email] => [email protected])

Page 6: Php Si Mysql

Obtin deci exact informatiile pe care intentionam sa le obtin cu instructiunea sql respectiva. Cateva explicatii referitoare la ceea ce se intampla in scriptul select.php:

mysql_query() returneaza o valoare de tip resource, ce contine setul de inregistrari, si pastram aceasta valoare in variabila $result

ganditi-va la $result ca la un tabel temporar (cu coloane si linii) ce poate fi accesat doar prin functiile mysql_fetch_row(), mysql_fetch_assoc(), mysql_fetch_array()

"tabelul temporar" sau setul de inregistrari tinut in $result, are exact atatea coloane cate am specificat in clauza SELECT, si atatea randuri cat ne returneaza query-ul (instructiunea sql) respectiva, in functie de clauza WHERE sau LIMIT pe care o specificam. Deci nu neaparat are numarul de coloane (sau randuri) al tabelului original.

functiile de tip mysql_fetch_*() au urmatoarea proprietate: de fiecare data cand se apeleaza, extrag sub forma de tablou doar o inregistrare (un rand) din setul de inregistrari, incepand cu prima inregistrare. Dupa ce a fost extrasa o inregistrare, pointerul intern al variabilei $result inainteaza la urmatoarea inregistrare (similar cu functia next() de la tablouri). La urmatoarea apelare, extrage intr-un tablou urmatoarea inregistrare, muta pointer-ul....etc. Astfel, daca stim sigur ca avem un singur rezultat (o singura inregistrare) obtinut prin instructiunea sql, putem folosi direct $d = mysql_fetch_assoc($result). Daca avem mai multe randuri, trebuie sa folosim constructia while ($d = mysql_fetch_assoc($result)) {...

explicatia constructiei while ($d = mysql_fetch_assoc($result)) { este urmatoarea: desi poate la prima vedere ar trebui sa se foloseasca operatorul de comparare "==" si nu cel de atribuire "=", aici nu se intentioneaza comparatia lui $d cu mysql_fetch_assoc($result) ci se atribuie rezultatul lui mysql_fetch_assoc($result) variabilei $d. Astfel, $d devine prima inregistrare, se executa bucla, $d devine a doua inregistrare, etc. In momentul cand pointer-ul din $result ajunge la sfarsit, mysql_fetch_assoc($result) va returna false. In momentul cand false este atribuit variabilei $d, valoarea expresiei $d = false este valoarea atribuita adica false; in acel moment bucla while se opreste.

Transformarea scriptului select.php din script didactic in script folositor, pe intelesul utilizatorului, este simpla:

select2.php 123456789

10111213141516171819202122232425262728

<?phpinclude("conectare.php"); $sql = 'SELECT utilizatorId, username, email FROM utilizatori ORDER BY utilizatorId DESC LIMIT 3';$result = mysql_query($sql) or die(mysql_error()); $str = '<table border="1" style="border-collapse: collapse;border: 1px solid gray;" cellpadding="3">'; $str .= '<tr>';$str .= '<th>utilizatorId</th>';$str .= '<th>username</th>';$str .= '<th>email</th>';$str .= '</tr>'; while ($d = mysql_fetch_assoc($result)) { $str .= '<tr>'; $str .= '<td>' . $d["utilizatorId"] . '</td>'; $str .= '<td>' . $d["username"] . '</td>'; $str .= '<td>' . $d["email"] . '</td>'; $str .= '</tr>';} $str .= '</table>'; echo $str; ?>

Alte functii mysqlObtinerea numarului de randuri dintr-un SELECTSe poate face in doua moduri, in functie de ce avem nevoie:

Page 7: Php Si Mysql

1. Daca vrem sa obtinem informatie din tabelul respectiv, si sa numaram randurile din variabila $result obtinuta, putem folosi mysql_num_rows() cu urmatorul prototip: int mysql_num_rows ( resource $result )

Exemplu:

select.php 123456789

1011121314151617181920212223242526272829303132333435

<?phpinclude("conectare.php"); $sql = 'SELECT utilizatorId, username, email FROM utilizatori WHERE sex = "m" ORDER BY utilizatorId ';$result = mysql_query($sql) or die(mysql_error()); if (mysql_num_rows($result) > 0) {$str = 'Am obtinut <b>' . mysql_num_rows($result). ' </b> rezultate <br />'; $str .= '<table border="1" style="border-collapse: collapse;border: 1px solid gray;" cellpadding="3">'; $str .= '<tr>';$str .= '<th>utilizatorId</th>';$str .= '<th>username</th>';$str .= '<th>email</th>';$str .= '</tr>'; while ($d = mysql_fetch_assoc($result)) { $str .= '<tr>'; $str .= '<td>' . $d["utilizatorId"] . '</td>'; $str .= '<td>' . $d["username"] . '</td>'; $str .= '<td>' . $d["email"] . '</td>'; $str .= '</tr>';} $str .= '</table>'; } else { $str = 'Nu am obtinut nici un rezultat'; } echo $str; ?>

2. Daca vrem doar sa numaram randurile obtinute printr-un SELECT, optim este sa obtinem numarul de randuri direct din MySQL cu sintaxa SELECT count(*) ...

123456789

101112

<?phpinclude("conectare.php"); $sql = 'SELECT COUNT(*) FROM utilizatori WHERE sex = "m" ORDER BY utilizatorId ';$result = mysql_query($sql) or die(mysql_error()); /*folosim mysql_fetch_row() pentru ca setul de inregistrari are o singura coloana si un singur rand. $d[0] este informatia cautata*/ $d = mysql_fetch_row($result);

Page 8: Php Si Mysql

131415

echo 'Am gasit <b>' . $d[0] . '</b> inregistrari. ' ;?>

Obtinerea numarului de randuri afectate de un UPDATE, SELECT, INSERT, DELETEReamintim functia mysql_affected_rows() cu urmatorul prototip: Pseudocodint mysql_affected_rows ([ resource $link_identifier ] )Parametrul primit de aceasta functie este optional, reprezinta conexiunea catre baza de date, in lipsa acestui parametru se foloseste conexiunea curenta. Returneaza numarul de randuri afectate de ultimul query trimis catra baza de date respectiva. Query-ul trebuie sa fie de tipul: UPDATE, SELECT, INSERT, DELETE. Obtinerea numelor si numarului de coloane din $resultUneori, vrem sa obtinem in mod dinamic numele coloanelor dintr-un set de inregistrari. Apelam functia mysql_field_name($result, $index), unde $result este bineinteles rezultatul apelarii unui query de tip SELECT cu mysql_query() si $index este pozitia coloanei din setul de inregistrari. Numarul coloanelor il obtinem cu mysql_num_fields($result).

123456789

10111213141516171819

<?phpinclude("conectare.php"); $sql = 'SELECT utilizatorId, username, email FROM utilizatori WHERE sex = "m" ORDER BY utilizatorId ';$result = mysql_query($sql) or die(mysql_error()); echo '<table border="1">';echo '<tr>'; for ($i = 0; $i < mysql_num_fields($result); $i++) { $numeCamp = mysql_field_name($result, $i); echo '<th>'.$numeCamp.'</th>'; } echo '</tr>'; echo '</table>' ?>

Obtinerea in PHP a structurii unui tabel MySQLDesi mai rar, avem poate uneori nevoia sa obtinem informatiile despre coloanele unui tabel MySQL. Putem folosi instructiunea sql 'SHOW COLUMNS FROM nume_tabel' si voi obtine un set de inregistrari cu o inregistrare pentru fiecare coloana a tabelului.

123456789

10

<?phpinclude("conectare.php"); $sql = 'SHOW COLUMNS FROM utilizatori';$result = mysql_query($sql) or die(mysql_error()); while ($d = mysql_fetch_assoc($result)) { print_r($d); }?>

Folosirea functiei mysql_real_escape_string()Folosirea acestei functii (sau altor functii similare) ne fereste de atacurile tip "SQL Injection Attack" prin care atacatorul completeaza anumite valori in formularele HTML (sau parametri GET) astfel incat samodifice instructiunea sql folosita de noi in script. Aceasta functie anuleaza orice caracter special (ghilimea simpla ('), dubla ("), newline (\n) ) din string-ul respectiv prin adaugarea caracterului backslash (\) in fata acestor caractere. Astfel, in instructiunea sql orice caractere speciale isi pierd semnificatia. Daca tabelul nostru ar avea o coloana de parola, o instructiune sql pentru autentificare (gasirea unui utilizator cu un username si o parola) ar arata astfel:

1 <?php

Page 9: Php Si Mysql

23456789

1011121314151617181920212223

include("conectare.php"); $username = $_POST["username"];$parola = $_POST["parola"]; if (get_magic_quotes_gpc()) { $username = stripslashes($username); $parola = stripslashes($parola); } $username = mysql_real_escape_string($username);$parola = mysql_real_escape_string($parola); $sql = "SELECT * FROM utilizatori WHERE username = '$username' AND parola = '$parola' ";echo $sql;$result = mysql_query($sql) or die(mysql_error()); while ($d = mysql_fetch_assoc($result)) { print_r($d); }?>

NotaExista o setare in php.ini (fisierul de configurare al PHP-ului) numita magic_quotes_gpc. Aceasta setare nu poate fi modificata cu ajutorul functiei ini_set() deci este in controlul celui care administreaza serverul respectiv (desi pot fi gasite metode "pe langa", vezi Resurse). Aceasta setare a devenit invechita, insa este folosita inca implicit pe serverele de gazduire la configurarea PHP-ului. Cand este setata (are valoarea 1), toate informatiile ce ajung de la utilizator (din get, post sau cookie) vor fi modificate astfel incat sa aiba backslash (\) in fata caracterelor ghilimea simpla ('), ghilimea dubla (") sau NULL. Puteti verifica daca aceasta setare este activa folosind functia get_magic_quotes_gpc(). Daca returneaza 1, inseamna ca setarea este activa, si pentru a obtine string-ul initial trebuie sa-i aplicati functia stripslashes() ce scoate backslash-urile. Apoi, daca folositi valorile respective in instructiuni sql, le puneti la loc dar cu mysql_real_escape_string().

NotaSubiectele "SQL Injection Attack", si "escape-ul" sirurilor de caractere primite de la utilizator este ceva mai amplu si nu vor fi dezbatute pe larg aici. Puteti consulta linkurile din sectiunea Resurse pentru mai multa informatie.

Extensia mysqliFunctiile mysqli_*Extensia mysqli contine atat interfata procedurala (set de functii) cat si interfata orientata obiect (clase si metode) pentru lucrul cu MySQL din PHP. Deci aceeasi functionalitate este oferita de fiecare din modalitatile de lucru alese (cu functii sau cu clase si metode), alegerea este a programatorului. In continuare voi prezenta principalele functii din extensia mysqli, ce sunt foarte asemanatoare (ca nume si functionalitate) cu cele din extensia mysql, cu urmatoarele diferente de retinut:

numele functiilor incep cu mysqli_ mysqli_connect() primeste un al patrulea argument - numele bazei de date selectate astfel incat sa nu mai fie

nevoie apelarea functiei mysqli_select_db() variabila ce pastreaza conexiunea la baza de date (returnata de functia mysqli_connect()), denumita in

general $link, va fi necesara ca prim argument la functii ce au nevoie de o conexiune activa, cum ar fi mysqli_query(). In functiile din extensia mysql acest argument era pe a 2-a pozitie pentru mysql_query() si era optional.

exista doua functii suplimentare pentru detectarea erorilor, mai precis pentru detectarea erorilor la conectare. Acestea sunt mysqli_connect_error() - returneaza mesajul erorii, si mysqli_connect_errno(). Celelalte functii ce returneaza ultima eroare generata de serverul MySQL sunt similare, si anume: mysqli_error() si mysqli_errno().

functia mysqli_query() primeste un al treilea parametru, constanta MYSQLI_USE_RESULT (implicit) sau MYSQLI_STORE_RESULT.

Page 10: Php Si Mysql

o daca este folosit MYSQLI_STORE_RESULT setul de rezultate este extras integral in memoria calculatorului pe care ruleaza PHP dar permite un acces rapid la inregistrari

o daca este folosit MYSQLI_USE_RESULT inregistrarile din setul de rezultate sunt extrase din serverul MySQL pe masura ce sunt accesate in PHP. Acest mod de lucru este potrivit pentru seturi mari de inregistrari, caz in care informatia nu trebuie stocata integral in memorie.

Codul de conectare la baza de date folosind functia mysqli_connect() ar putea arata astfel: conectare.php

123456789

101112131415

<?php $db_host = 'localhost';$db_user = 'root';$db_pass = '';$db_name = 'mysite'; $link = @mysqli_connect($db_host, $db_user, $db_pass, $db_name); if (!$link) { die('Eroare la conectare: ' . mysqli_connect_error());} ?>

Functia mysqli_connect() va returna FALSE in cazul esuarii conexiunii, si un obiect de tip mysqli in caz de succes, sau mai simplu, o variabila ce reprezinta conexiunea la serverul MySQL. Scriptul prin care realizam un select dintr-un tabel, devine:

select.php 123456789

10111213

<?php include("conectare.php"); $sql = 'SELECT * FROM utilizatori';$result = mysqli_query($link, $sql); while ($d = mysqli_fetch_assoc($result)) { print_r($d);} ?>

NotaRestul functiilor sunt si ele asemanatoare cu cele din extensia mysql: mysqli_fetch_row(), mysqli_fetch_array(), mysqli_num_rows(), mysqli_affected_rows(), ....

Folosirea tranzactiilor cu MySQL din PHPCe sunt tranzactiile ?In sistemele de baze de date tranzactiile sunt un concept important si foarte necesar in anumite cazuri. Tranzactiile inseamna suport din partea serverului de baze de date pentru tratarea unei secvente de instructiuni sql ca un grup unitar. Practic, una din consecintele principale este ca aceste instructiuni sql se executa toate cu succes, sau nici una. Un exemplu usor de inteles pentru necesitatea tranzactiilor este cel in care lucram cu baza de date a unei banci, si avem un tabel conturi in care operam mutarea unei sume dintr-un cont in altul. Cele doua query-uri arata astfel: query 1: UPDATE conturi SET sold = sold - 100 WHERE clientId = 23; query 2: UPDATE conturi SET sold = sold + 100 WHERE clientId = 499; Daca dintr-un motiv query 2 nu este executat (pana de curent, eroare de aplicatie, etc) atunci scade soldul primului client dar suma nu se muta in contul celui de-al doilea client, lucru ce nu corespunde cu realitatea si apare astfel o inconsistenta a bazei de date. Grupand aceste doua query-uri intr-o tranzactie, serverul MySQL executa aceste instructiuni dar nu le face permanente, astfel incat daca una din ele esueaza instructiunile pot fi anulate (un fel de undo). Plus ca, in timp ce o tranzactie se desfasoara, ceilalti clienti ce se conecteaza la serverul MySQL nu citesc datele modificate decat daca tranzactia este incheiata. Tranzactiile in MySQL. Un simplu exemplu.

Page 11: Php Si Mysql

Tranzactiile au aparut in MySQL incepand cu versiunea 4.0 si sunt suportate de tipul de tabele InnoDB. In MySQL exista mai multe tipuri de tabele sau "storage engines" cum le numeste echipa MySQL. Cele mai folosite sunt MyISAM, tipul implicit pentru tabelele noi create. InnoDB are ca principal avantaj fata de MyISAM suportul pentru tranzactii. Pentru diferitele tipuri de "storage engines" si diferentele dintre ele consultati sectiunea Resurse. Deci, inainte sa testati sau sa folositi tranzactiile, asigurati-va ca lucrati pe un tabel InnoDB. In MySQL exista urmatoarele instructiuni principale ce ne ajuta sa lucram cu tranzactii:

START TRANSACTION; sau BEGIN;- incepe o tranzactie COMMIT; - finalizeaza tranzactia curenta ROLLBACK - daca tranzactia nu s-a finalizat, putem sa anulam instructiunile executate pana atunci din cadrul

tranzactieiMySQL lucreaza in mod implicit in modul AUTOCOMMIT, adica automat fiecare instructiune ce nu face parte dintr-o tranzactie este finalizata (ca si cum am specifica COMMIT; la sfarsitul ei). Pot sa schimb acest comportament cu instructiunea sql: SET AUTOCOMMIT = 0; Pentru a vedea la un moment dat ce valoare are variabila AUTOCOMMIT (0 sau 1) pot folosi instructiunea: SELECT @@autocommit; Utilizand baza de date mysite, si doua linii de comanda mysql (deci doi clienti MySQL conectati in acelasi timp la server) voi sterge utilizatorul horatiu, avand utilizatorId = 1 din tabelul utilizatori, si mesajele corespondente din tabelul mesaje. Folosind tranzactii: am posibilitatea sa anulez oricand instructiunile realizate inainte de finalizarea tranzactiei, si in plus, voi observa cum celalalt client conectat nu vede modificarea decat atunci cand tranzactia este incheiata. 1. In prima etapa, in conexiunea principala (stanga) transform tabelele bazei de date mysite la tipul InnoDB, pentru a avea acces la lucrul cu tranzactii pe aceste tabele. Selectez apoi inregistrarile utilizatorului cu utilizatorId = 1 din ambele tabele.

2. Incep tranzactia, cu START TRANSACTION. Rezultatul query-urilor din tranzactie se vad in conexiunea principala (deci randurile sunt sterse), dar conexiunea din dreapta nu vede efectul query-urilor din tranzactia in derulare.

Page 12: Php Si Mysql

3. Folosind instructiunea ROLLBACK am posibilitatea sa anulez query-urile din tranzactia respectiva (daca detectez de exemplu ca un query nu s-a executat cu succes), pentru ca tranzactia nu a fost inca finalizata, deci modificarile nu au fost permanente.

Page 13: Php Si Mysql

4. a. Reiau tranzactia, execut START TRANSACTION b. Execut cele doua instructiuni DELETE c. In conexiunea din dreapta realizez instructiunile SELECT, inregistrarile sunt inca acolo, pentru ca tranzactia din prima conexiune nu a fost finalizata d. In conexiunea din stanga, execut COMMIT e. Instructiunile au fost executate, sunt permanente, se vad si pentru celelalte conexiuni

Folosirea tranzactiilor in MySQL din PHPExtensiile mysqli si PDO permit lucrul cu tranzactiile MySQL. Functiile mysqli pentru folosirea tranzactiilor sunt: 1. mysqli_autocommit - seteaza modul autocommit pentru conexiunea $link Pseudocodbool mysqli_autocommit ( mysqli $link , bool $mode )2. mysqli_commit - echivalent cu instructiunea COMMIT - finalizeaza o tranzactie Pseudocodbool mysqli_commit ( mysqli $link )3. mysqli_rollback - echivalent cu ROLLBACK - anuleaza tranzactia curenta si query-urile executate pana atunci Pseudocodbool mysqli_rollback ( mysqli $link )

Exemplu: 123456789

101112131415

<?phpinclude("conectare.php"); $rollback = 0; $sql[] = 'DELETE FROM utilizatori WHERE utilizatorId = 1';$sql[] = 'DELETE FROM mesaje WHERE utilizatorId = 1'; mysqli_autocommit($link, false); foreach ($sql as $s) { $ok = mysqli_query($link, $s); if ($ok === FALSE) $rollback = 1; // daca un query returneaza FALSE (a esuat), variabila rollback devine 1

Page 14: Php Si Mysql

161718192021222324

} if ($rollback == 1) { mysqli_rollback($link); } else { mysqli_commit($link); }?>

NotaDesi tranzactiile reprezinta un element important al bazelor de date, intr-o aplicatia web medie probabil nu e nevoie in general de tranzactii. Daca in schimb se lucreaza cu date financiare sau alte date sensibile in care e extrem important sa se pastreze consistenta datelor si baza de date (implicit website-ul) este foarte accesata, si mai mult, exista probabilitatea reala ca mai multi utilizatori sa citeasca/modifice acelasi randuri dintr-un tabel atunci tranzactiile devin necesare. Daca insa folositi tranzactii, trebuie sa lucrati cu tabele InnoDB.

NotaPentru alte exemple ce demonstreaza avantajele tranzactiilor, si pentru mai multe informatii, consultati linkurile din sectiunea Resurse

Folosirea "prepared statements"Utilizarea "prepared statements" (procedurilor stocate) permite refolosirea unei instructiuni MySQL cu argumente diferite , si prezinta urmatoarele avantaje:

in general sunt mai rapide decat varianta clasica (trimiterea unei instructiuni sql complete catre MySQL) datorita faptului ca instructiunea sql a fost deja compilata pe server MySQL, si nu se transmit spre server decat parametrii necesari

sunt mai sigure pentru ca parametrii folositi in query, trimisi catre server, sunt automat verificati, iar toate caracterele speciale sunt anulate, precedate de backslash. Este ca si cum valorile primite de server ar fi trecute prin functia mysql_real_escape_string

Exemplu: 123456789

101112131415161718192021222324252627282930

<?phpinclude("conectare.php"); $sql = 'SELECT subiect, mesaj, dataMesaj FROM mesaje WHERE DATE_FORMAT(dataMesaj, "%Y-%m-%d") = ? AND utilizatorId = ? ORDER BY dataMesaj DESC';$stmt = mysqli_prepare($link, $sql); $dataMesaj = '2009-04-27';$utilizatorId = 1; mysqli_stmt_bind_param($stmt, 'sd', $dataMesaj, $utilizatorId);mysqli_stmt_execute($stmt); mysqli_bind_result($stmt, $subiect, $mesaj, $dataMesaj); echo '<table border="1">';while (mysqli_stmt_fetch($stmt)) { // vezi capitolul Tipuri de date - string - heredocecho <<<A<tr> <td>$subiect</td> <td>$mesaj</td> <td>$dataMesaj</td></tr>A; } /// while echo '</table>';

Page 15: Php Si Mysql

31 ?>

Functiile folosite in acest exemplu sunt: mysqli_prepare - primeste ca parametru o variabila a conexiunii la baza de date ($link) si o instructiune sql

($query) ce reprezinta procedura stocata ("the prepared statement"). In aceasta instructiune sql, parametrii sau valorile pe care vrem sa le transmitem ulterior, sunt inlocuite cu semnul intrebarii (?) . Functia returneaza o variabila (obiect) de tip mysqli_stmt. Pseudocodmysqli_stmt mysqli_prepare ( mysqli $link , string $query )

mysqli_bind_param - primeste ca prim parametru o variabila de tip mysqli_stmt (returnata de mysqli_prepare), apoi un string format din litere ce reprezinta tipul parametrilor transmisi catre instructiunea sql, astfel: i pentru integer, d pentru double, s pentru string, b pentru blob. De la al treilea parametru in sus, se primesc numele variabilelor al caror continut va fi transmis catre server pentru a inlocui simbolul ? in procedura stocata. Astfel, daca vreau sa trimit un string si un intreg, functia va fi apelata de exemplu: mysqli_stmt_bind_param($stmt, 'si', $nume, $varsta); Pseudocodbool mysqli_stmt_bind_param ( mysqli_stmt $stmt , string $types , mixed &$var1 [, mixed &$... ] )

mysqli_stmt_execute - executa o variabila de tip mysqli_stmt, deci o "prepared statement", sau procedura stocata. Procedura a fost initial pregatita (trimisa catre server) cu mysqli_prepare(), apoi au fost trimise si valorile parametrilor prin mysqli_bind_param. la apelarea acestei functii, instructiunea este executata pe serverul MySQL. Pseudocodbool mysqli_stmt_execute ( mysqli_stmt $stmt )

mysqli_bind_result - "leaga" numele unor variabile de valorile aflate la un moment dat intr-o inregistrare din setul de inregistrari Pseudocodbool mysqli_stmt_bind_result ( mysqli_stmt $stmt , mixed &$var1 [, mixed &$... ] )

mysqli_stmt_fetch - extrage cate o inregistrare din setul de inregistrari obtinut prin executia query-ului, si la fiecare apelare (presupunem ca o folosim intr-un while) va returna valorile obtinute pentru fiecare camp in variabilele "legate" cu mysqli_bind_result. Daca nu mai sunt randuri in setul de inregistrari, va returna NULL. Pseudocodbool mysqli_stmt_fetch ( mysqli_stmt $stmt )

Interfata obiectuala a mysqliNota

Folosirea claselor si a altor concepte ale programarii orientate obiect vor fi explicate in detaliu in capitolul "Clase si obiecte".

Metodele clasele extensiei mysqli se regasesc si in interfata procedurala, dar bineinteles, putin modificate, in general cu mai putini parametri. In documentatia oficiala PHP, sunt tratate in paralel. Exista 3 clase principale ale extensiei mysqli.

mysqli - obiectele din aceasta clasa reprezinta conexiuni la serverul de baze de date. mysqli_stmt - reprezinta o procedura stocata (prepared statement) mysqli_result - obiectele contin rezultatele obtinute in urma executarii unui query. Metodele din aceasta

clasa corespund functiilor mysqli_fetch_row(), mysqli_fetch_array() si mysqli_fetch_assoc() si extrag informatiile din rezultatul executiei.

123456789

10

<?php $db_host = 'localhost';$db_user = 'root';$db_pass = 'iesire';$db_name = 'mysite'; $mysqli = @new mysqli($db_host, $db_user, $db_pass, $db_name); if (mysqli_connect_error()) {

Page 16: Php Si Mysql

1112131415161718192021

die('Eroare conexiune: ' . mysqli_connect_error()); } $sql = 'SELECT * FROM utilizatori';$result = $mysqli->query($sql); while ($d = $result->fetch_assoc()) { print_r($d); } ?>