4 Jul 2011 1 commenti
Il sistema PDO per il suo funzionamento si serve di tre classi:
- PDO: esegue la connessione, gestisce le transazioni (che vedremo nel prossimo articolo) e per eseguire le query crea le istanze della classe PDOStatement;
- PDOStatement: gestisce i risultati ottenuti con le query eseguite (operazioni di fetch, conteggio delle righe estratte, etc. etc.);
- PDOException: gestisce le eccezioni sollevate nell'utilizzo del sistema PDO.
Nel precedente articolo si è illustrato il modo in cui ci si connette al nostro database con la classe PDO e le diverse modalità per gestire gli errori SLQ generati dall'interazione con esso. In particolare ci si è soffermati al modo in cui intercettare le eccezioni gestite dalla classe PDOExecption.
A questo punto passiamo ad esaminare le modalità di esecuzione delle diverse tipologie di query. Infatti a seconda della tipologia di query che andremo ad effettuare vi saranno metodi specificatamente indicati (o consigliati).
Query di tipo SELECT
Iniziamo questa disamina iniziando dalle query di tipo SELECT per estrarre i dati dal nostro database.
Per questa tipologia di query potremo utilizzare il metodo PDO->query(). Tale metodo ci darà come return il result set come un oggetto PDOStatement (più complicato a dirsi che a vederlo all'opera).
Il suo impiego è consigliabile quando la query è di tipo "statico" cioè non prevede input dinamici esterni.
Per proteggerci dalle SQL Injection dovremo, infatti, eseguire "manualmente" l'escape delle stringhe struttando il metodo PDO->quote(). Inoltre a seconda della tipologia di campo su cui andremo ad eseguire le query occorreranno le apposite funzioni per "filtrare" i dati in ingresso (intval, floatval, etc.).
Per eseguire la selezione dei dati dal database faremo molto semplicemente:
$sql = "SELECT * FROM people WHERE name= " . $PDO->quote($_POST['name']); foreach( $PDO->query($sql) as $row ){ var_dump($row); }
Le diverse modalità di fetch
Ci sono diverse modalità per recuperare i dati. Infatti con MySql siamo abituati ad utilizzare mysql_fetch_row(), mysql_fetch_array(), o mysql_fetch_assoc().
La modalita con cui eseguire il fetch potrà essere indicata come parametro del metodo PDOStatement->fetch() o impostandola con il metodo PDOStatement->setFetchMode.
Nel primo caso avremo che:
$statement = $PDO->query("SELECT * FROM people"); while($row = $statement->fetch(PDO::FETCH_ASSOC)){ var_dump($row); }
Nel secondo caso, con analogo effetto, avremo che:
$statement = $PDO->query("SELECT * FROM people"); $statement->setFetchMode(PDO::FETCH_ASSOC); while($row = $statement->fetch()){ var_dump($row); }
Il valore di defaul di tale parametro è PDO::FETCH_BOTH che ci darà come return un array in cui ogni elemento è presente sia con chiave letterale che con chiave numerica (così come accade con mysql_fetch_array()).
Query di tipo DELETE e UPDATE
Nel caso di query di tipo DELETE e UPDATE è possibile impiegare il metodo PDO->exec(). Questo metodo ci restituirà il numero di record coinvolti (affected) nella query.
$affected = $dbh->exec("DELETE FROM people WHERE id = 5"); echo 'Righe eliminate ' . $affected;
Questa tipologia di query richiede le medesime attenzioni esaminate per il precedente caso: cioè l'utilizzo è consigliato per query di tipo "statico" e, laddove necessario, occorre eseguire l'escape delle stringhe nonchè gli altri controlli necessari per prevenire SQL Injection.
Occorre osservare che una query che non elimina/modifica nessun record ci darà come return 0 (zero). Per tale ragione occorre prestare attenzione a non fare questo tipo di errore:
//sbagliato fare in questo modo $PDO->exec("DELETE people WHERE id = 5") or die("query fallita"); // esatto $affected = $PDO->exec("DELETE people WHERE id = 5"); if($affected === FALSE){ die("query fallita"); }
Si noti l'uso dell'operatore === nel verificare che il risultato sia FALSE.
Prepared statement
La modalità da preferire quando si eseguono le query al nostro database è sicuramente quella basata sui prepared statements: questa garantisce migliori prestazioni e consente di proteggerci in modo sicuro dalle SQL Injection.
Il suo utilizzo è consigliato con tutte el tipologie di query che andremo ad effettuare.
Nel caso visto in precedenza della SELECT avremo:
$n = $_POST['name']; $statement = $PDO->prepare('SELECT * FROM people WHERE name = :name'); $statement->bindParam(':name', $n, PDO::PARAM_STR); $statement->execute(); while($row = $statement->fetch() ){ echo var_dump($row); }
Nel caso, invece, di una query di tipo INSERT avremo:
$n = "Paul"; $a = 26; $statement = $PDO->prepare("INSERT INTO people (name, age) VALUES(:name, :age)"); $statement->bindParam(':name', $n, PDO::PARAM_STR, 255); $statement->bindParam(':age', $a, PDO::PARAM_INT); $statement->execute();
Oppure, ancora, con sintassi diversa ma analoghi risultati avremo:
$n = "Paul"; $a = 26; $statement = $PDO->prepare("INSERT INTO people (name, age) VALUES(?, ?)"); $statement->bindParam(1, $n, PDO::PARAM_STR, 255); $statement->bindParam(2, $a, PDO::PARAM_INT); $statement->execute();
Dal punto di vista teorico il metodo PDO->prepare() ci darà come return un oggetto PDOStatement: in particolare esso "prepara" la query in attesa di esecuzione che avverrà con PDOStatement->execute().
I namespace (:namespace) o i punti interrogativi (question mark) verranno associati con i metodi PDOStatement->bindParams() (da utilizzare con le variabili) o PDOStatement->bindValue().
Inoltre, in caso di una query INSERT, per conoscere l'id auto-increment dell'ultimo record inserito potremo impiegae il metodo PDO->lastInsertId().
Altri metodi previsti
A questo punto non rimane da fare che una rapida carrellata degli altri metodi che l'oggetto PDOStatement ci mette a disposizione.
Un metodo molto utile è PDOStatement->fetchAll() che ci darà come return un array contenente tutte le righe che compongono il result set di una query SELECT.
$st = $PDO->prepare("SELECT * FROM people"); $st->execute(); $array_select = $st->fetchAll(); print_r($array_select);
Il metodo PDOStatement->rowCount() ci darà come return il numero di record coinvolti attraverso query di tipo DELETE, INSERT, o UPDATE.
$statement = $PDO->prepare("DELETE FROM people"); $statement->execute(); echo $statement->rowCount();
Nel caso di una SELECT questo metodo, pur potendo funzionare su alcuni tipi di database, è fortemente sconsigliato. Per effettuare tale operazione in modo corretto e salvaguardare la portabilità del nostro applicativo fra le diverse tipologie di database il manuale ufficiale consiglia di agire nel modo in cui segue:
$sql = "SELECT COUNT(*) FROM people"; $statement = $PDO->query($sql); echo 'Count rows selected: ' . $statement->fetchColumn();
Attenzione a gestire gli errori
Al fine di rendere snello il codice riportato negli esempi si è totalmente trascurata la gestione degli errori. Tuttavia questa, nelle diverse modalità descritte nel precedente articolo, è sempre opportuna.
Conclusioni
Il presente articolo è solo una rapida e parziale carrellata degli strumenti che il sistema PDO ci mette a disposizione per gestire le query e, ovviamente, non può essere considerato esaustivo. Per tale ragione si rimanda al manuale ufficiale per i dettagli di ciascun metodo.
Per finire l'illustrazione del PDO non ci rimane che affrontare una parte che ritengo (opinione personale) molto interessante: le transazioni. Questo sarà oggetto del mio prossimo (e conclusivo) articolo.
Olimpio Romanella
Sono un appassionato di Web Developing con un particolare debole per php. Mi dedico principalmente dello sviluppo back-end ed in particolare programmazione lato server con php, sviluppo di database relazionali MySql e progettazione di CMS di piccole e medie dimensioni.
Mi avvalgo del framework javascript Jquery, utilizzando molti dei suoi plugin e nei dei miei progetti utilizzo spesso il framework MVC Codeigniter.
Robert
25 February 2019 ore 07:30