back to top

PHP e MySQL: prepared statements con PDO

Chi ha ricercato in Rete informazioni sui Prepared statements (o "istruzioni parametrizzate"), avrà notato come questi ultimi vengano spiegati non di rado in modo abbastanza contorto; proviamo quindi a darne una definizione quanto più semplice e comprensibile possibile.

In linea di massima i Prepared statements si possono definire come dei template (cioè degli schemi) destinati ad inviare dei dati ad una tabella, questi ultimi potranno essere utilizzati per l’esecuzione di istruzioni di vario tipo, dall’inserimento di valori alla loro estrazione, dall’aggiornamento dei record alla loro cancellazione. Il fatto che essi rappresentino dei template presuppone tre diversi vantaggi nell’utilizzo dei Prepared statements:

  • sono più sicuri rispetto all’invio di istruzioni SQL nel loro formato originale;
  • sono riutilizzabili e quindi consentono di ottimizzare il codice di un’applicazione;
  • migliorano il livello generale delle prestazioni nelle operazioni che prevedono l’interazione con i database.

Per quanto riguarda la sicurezza, i Prepared statements si rivelano particolarmente utili nella prevenzione degli attacchi basati sulla SQL Injection, cioè l’iniezione di codice malevolo tramite istruzioni SQL, questo per il semplice motivo che i Prepared statements separano l”SQL dai dati, quindi, anche nel caso in cui in essi sia presente del codice malevolo, questo non verrà eseguito perché non farà parte della query SQL. Dato che la parte relativa ad SQL diventa un template, tale schema potrà essere riutilizzato quando si desidera effettuare lo stesso tipo di istruzione, nel momento in cui viene effettuata la formazione del template essa potrebbe pesare sulle performances dell’applicazione di riferimento, nel complesso però la sua riutilizzabilità dovrebbe poi influire positivamente sulle prestazioni.

Alla base della dinamica che porta alla generazione dei template nei Prepared statements vi è un meccanismo denominato binding dei parametri, esso prevede in pratica che al posto dei valori vengano passati in query dei placeholder (dei nomi che fungono da "segnaposto"), questi ultimi saranno successivamente vincolati (da qui l’utilizzo del termine "binding") a dei parametri da utilizzare per completare le operazioni di inserimento, selezione, aggiornamento o cancellazione dei dati.

Per fare un esempio, si immagini che la nostra tabella "contatti" del database "nominativi" contenga anche il campo numerico intero "anni_vissuti" e di voler estrarre da essa il record che corrisponda al "cognome = ‘Pellico’" e ad "anni_vissuti = 64"; il primo passaggio da effettuare sarà quello di definire due variabili da associare ai due valori precedentemente introdotti.

// definizione delle variabili per la query
$contatto_cognome = "Pellico";
$contatto_anni_vissuti = 64;

Ora che tali variabili sono state memorizzate sarà possibile lasciarle da parte per un attimo e passare alla definizione del template. Esso viene passato come parametro al metodo prepare() e assume una forma simile a quella di un query (anche se in realtà non lo è) dove i valori vengono sostituiti dai segnaposto che, nel caso specifico sono ":contatto_cognome" e ":contatto_anni_vissuti".

// preparazione della query SQL
$sql = $connessione->prepare("SELECT nome FROM contatti WHERE cognome = :contatto_cognome AND anni_vissuti = :contatto_anni_vissuti");

Ora si potrà passare al vincolo tra variabili e segnaposto (binding), ciò potrà avvenire per ciascun valore passando all’apposito metodo bindParam() i parametri relativi al segnaposto utilizzato nel template, alla variabile che contiene il valore e al tipo di dato da associare a tale valore (nel nostro caso abbiamo un intero e una stringa, per quest’ultima è stata indicata anche la lunghezza, pari a 7 caratteri, tramite un ulteriore parametro). Vediamo il codice:

// bind dei parametri
$sql->bindParam(':contatto_cognome', $contatto_cognome, PDO::PARAM_STR, 7);
$sql->bindParam(':contatto_anni_vissuti', $contatto_anni_vissuti, PDO::PARAM_INT);

PDO::PARAM_STR e PDO::PARAM_INT sono delle costanti di classe utilizzate da PDO per PHP a partire dalla versione 5.1 di quest’ultimo per la rappresentazione di un data type SQL. A tal proposito potremo adottare le seguenti costanti:

  1. PDO::PARAM_BOOL: rappresenta un tipo di dato booleano;
  2. PDO::PARAM_NULL: rappresenta un tipo di dato SQL NULL (assenza di valore);
  3. PDO::PARAM_INT: rappresenta un tipo di dato numerico intero (SQL INTEGER);
  4. PDO::PARAM_STR: rappresenta un tipo di dato stringa (SQL CHAR, VARCHAR, TEXT..);
  5. PDO::PARAM_LOB: rappresenta un tipo di dato large object di SQL.

Il binding dei parametri consnetirà quindi di eseguire il Prepared statement tramite il metodo execute()

$sql->execute();

Esaminate nel dettaglio le caratteristiche di questi particolari costrutti, nel prossimo capitolo verranno proposti alcuni esempi pratici riguardanti l’utilizzo dei Prepared statements.

Pubblicitร 
Claudio Garau
Claudio Garau
Web developer, programmatore, Database Administrator, Linux Admin, docente e copywriter specializzato in contenuti sulle tecnologie orientate a Web, mobile, Cybersecurity e Digital Marketing per sviluppatori, PA e imprese.