Extensii pentru conectarea la baza de date în PHP


 21 Oct, 2014  doru  505  
php mysql mysqli pdo

Când vrei să te conectezi la baza de date MySQL din PHP ai la dispoziție trei modalități: folosind extensiile mysql sau mysqli sau clasa PDO (PHP Database Object - Obiectul bază-de-date în PHP ).

   

1. Extensia mysql

Este cea mai veche dintre cele trei și este în curs de a fi scoasă din uz în PHP 5.5.0, pe lângă aceasta, ultima ei revizuire a fost făcută prin 2002 și deci ultimele funcționalități din MySQL nu pot fi accesate prin intermediul ei. Nu ne vom ocupa în acest articol de ea (din motivele enumerate) și nici nu este recomandat ca cei care învață PHP acum să o studieze - poate numai din motive istorice și/sau dacă urmează să se ocupe cu cod PHP învechit.

2. Extensia mysqli

mysqli adică MySQLImproved - este varianta îmbunătățită a extensiei mysql. Are o IPA (API) atât procedurală cât și orientată pe obiecte. Conține 100 de funcții (față de 48, cât conține extensia mysql). Era metoda recomandată de conectare la baza de date până la apariția extensiei PDO.

3. Extensia/clasa PDO

Este cea mai nouă - și cea recomandată la momentul actual - modalitate de conectare la baza de date. Un mare avantaj față de mysqli este faptul că suportă 12 drivere de baze de date (nu numai pentru MySQL, cum suportă mysqli). Aceasta înseamnă că dacă la un moment dat trebuie să schimbi baza de date (să zicem că vrei/trebuie să folosești PostgreSQL) modificările pe care trebuie să le aduci codului sunt minime, pe când dacă ai folosit mysqli trebuie să modifici întreg codul care are legătură cu baza de date.

Comparare

În ambele conectarea la baza de date este foarte simplă:

// PDO
$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');
 
// mysqli, modlitatea procedurală
$mysqli = mysqli_connect('localhost','username','password','database');
 
// mysqli, modalitatea orientată pe obiect
$mysqli = new mysqli('localhost','username','password','database');

În PDO pentru a putea gestiona erorile care apar la conectare sau în timpul înterogărilor, obiectul conexiune și interogările (queries) trebuie puse întotdeauna într-un bloc try/catch :

# conectare la baza de date
try {
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
 
  # HOoopa! E tiparit DELECT în loc de SELECT!
  $DBH->prepare('DELECT nume FROM oameni');
}
catch(PDOException $e) {
    echo "Îmi pare rau, comanda este gresita.";
    

Dacă nu este folosit blocul try/catch mesajul de eroare trimis de PDO va putea conține date sensibile (nume de utilizatori și parole) reprezentând asfel o mare breșă de securitate. Deci folosiți întotdeauna un obiect conexiune și diferitele interogări ale bazei de date într-un bloc try/catch!

Un alt avantaj al extensiei PDO îl reprezintă parametrii numiți (named parameters):

$parametri = array(':username' =>$utilizator, ':email' => $mail, ':last_login' => time() - 3600);
     
$pdo->prepare('
    SELECT * FROM utilizatori
    WHERE username = :username
    AND email = :email
    AND last_login > :last_login');
     
$pdo->execute($parametri);

spre deosebire de parametrul semnul întrebării (question mark parameter) în mysqli:

$query = $mysqli->prepare('
    SELECT * FROM utilizatori
    WHERE utilizator = ?
    AND mail = ?
    AND last_login > ?');
     
$query->bind_param($utilizator, $mail, time() - 3600);
$query->execute();

...unde folosirea ? poate crea confuzii, mai ales când e vorba de mulți parametrii (pentru că trebuie ținut cont de ordinea acestora într-o interogare ). mysqli nu oferă suport pentru parametrii numiți.

Cam așa ar arăta o simplă interogare SELECT folosind PDO:

<?php 
	$db = new PDO("mysql:host=localhost;dbname=rocod", "rocoder", "rocoder123");
	$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	try {
		$queryStr = "SELECT * FROM utilizatori";
		$query = $db->prepare($queryStr);
		$query->execute();
		while ($row = $query->fetch()) {
			echo $row['id'] . ' - ' . $row['nume'] . ' - ' . $row['email'] . ' - ' . $row['parola'];
			echo '<br>';
		}
		$query->closeCursor();
	} catch (PDOException $e) {
		echo $e->getMessage();
	}
?>

Se observă folosirea metodei fetch() - aceasta ne aduce fiecare rând (row) din baza de date într-un array asociativ: cheia (key) este numele coloanei iar valoarea (value) este ce este pus în câmpul (field) respectiv - astfel putem accesa fiecare câmp (field) dintr-un rând (row) exact cum accesăm elementele dintr-un array asociativ folosind cheia (key) pe post de index. După ce am terminat de folosit conexiunea este întotdeauna recomandat să o închidem - pentru a elibera memoria folosită de PHP cu conexiunea - apelând metoda closeCursor(). Se mai observă faptul că punem să fie afișată eroarea (dacă apare vreuna):

 catch (PDOException $e) {
		echo $e->getMessage();
	}

Facem aceasta atunci când lucrăm în serverul de dezvoltare (development server) pentru că vrem să știm ce eroare este pentru a o putea gestiona. În producție vom afișa un mesaj de eroare particularizat fără a afișa conținutul erorii, de ex.:

catch(PDOException $e) {
    echo "Îmi pare rau, comanda este gresita.";

Dacă n-ați trecut până acum la Extensia/clasa PDO este recomandat s-o faceți cât mai repede: aceasta este metoda state of art de conectare la o(/mai multe) bază(/baze) de date în PHP.

(Ro)cod cu spor!