Sunteți pe pagina 1din 6

Functiile 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. 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 1 <?php 2 3 $db_host = 'localhost'; 4 $db_user = 'root'; 5 $db_pass = ''; 6 $db_name = 'mysite'; 7 8 9 $link = @mysqli_connect($db_host, $db_user, $db_pass, $db_name); 10 11 if (!$link) { 12 die('Eroare la conectare: ' . mysqli_connect_error()); 13 } 14 15 ?> 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 1 <?php 2 3 include("conectare.php"); 4 5 $sql = 'SELECT * FROM utilizatori'; 6 $result = mysqli_query($link, $sql); 7 8 while ($d = mysqli_fetch_assoc($result)) { 9 print_r($d); 10 } 11 12 13 ?> Nota

Restul 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 PHP Ce 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.


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 tranzactiei MySQL 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 ut

ilizatorId = 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.

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.

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 PHP Extensiile mysqli si PDO permit lucrul cu tranzactiile MySQL. Functiile mysqli pentru folosirea tranzactiilor sunt: 1. mysqli_autocommit - seteaza modul autocommit pentru conexiunea $link Pseudocod bool mysqli_autocommit ( mysqli $link , bool $mode ) 2. mysqli_commit - echivalent cu instructiunea COMMIT - finalizeaza o tranzactie Pseudocod bool mysqli_commit ( mysqli $link ) 3. mysqli_rollback - echivalent cu ROLLBACK - anuleaza tranzactia curenta si query-urile executate pana atunci Pseudocod bool mysqli_rollback ( mysqli $link ) Exemplu: 1 <?php 2 include("conectare.php"); 3 $rollback = 0; 4 $sql[] = 'DELETE FROM utilizatori WHERE utilizatorId = 1'; 5 $sql[] = 'DELETE FROM mesaje WHERE utilizatorId = 1'; 6 mysqli_autocommit($link, false); 7 foreach ($sql as $s) { 8 $ok = mysqli_query($link, $s); 9 if ($ok === FALSE) $rollback = 1; // daca un query returneaza FALSE (a esuat), variabila rollback 10 devine 1 11 } 12 if ($rollback == 1) { 13 mysqli_rollback($link); 14 } else { 15 mysqli_commit($link); 16 } 17 ?> 18 19 20 21 22 23 24 De

si 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. Pentru 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: 1 <?php 2 include("conectare.php"); 3 4 $sql = 'SELECT subiect, mesaj, dataMesaj FROM mesaje WHERE DATE_FORMAT(dataMesaj, 5 "%Y-%m-%d") = ? AND utilizatorId = ? ORDER BY dataMesaj DESC'; 6 $stmt = mysqli_prepare($link, $sql); 7 $dataMesaj = '2009-04-27'; 8 $utilizatorId = 1; 9 mysqli_stmt_bind_param($stmt, 'sd', $dataMesaj, $utilizatorId); 10 mysqli_stmt_execute($stmt); 11 mysqli_bind_result($stmt, $subiect, $mesaj, $dataMesaj); 12 echo '<table border="1">'; 13 while (mysqli_stmt_fetch($stmt)) { 14 // vezi capitolul Tipuri de date - string - heredoc 15 echo <<<A 16 <tr> 17 <td>$subiect</td> 18 <td>$mesaj</td> 19 <td>$dataMesaj</td> 20 </tr> 21 A; 22 } /// while 23 echo '</table>'; 24 ?> 25 26 27

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. Pseudocod mysqli_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); Pseudocod bool 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. Pseudocod bool 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 Pseudocod bool 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. Pseudocod bool mysqli_stmt_fetch ( mysqli_stmt $stmt ) Interfata obiectuala a mysqli 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. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?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()) { die('Eroare conexiune: ' . mysqli_connect_error()); } $sql = 'SELECT * FROM utilizatori'; $result = $mysqli->query($sql); while ($d = $result->fetch_assoc()) { print_r($d); } ?>