back to top

PHP: estrarre record da una tabella MySQL con PDO

Riassumendo quanto fatto fino a questo momento, possiamo ricordare che abbiamo utilizzato PDO per effettuare la connessione con il Database engine MySQL, creato un database (denominato "nominativi"), generato una tabella all’interno di quest’ultimo (chiamata "contatti") e popolato la tabella con dei campi ("id", "nome" e "cognome") per consentire l’inserimento dei record.

Le informazioni ora contenute in tabella possono essere estratte in vario modo e per diversi scopi, uno di questi è la semplice stampa a video dei record; il seguente script riporta la procedura necessaria per selezionare tutti i record ora presenti in tabella tramite un’istruzione SQL ("query") basata sul comando SELECT.

<?php
/*
  blocco dei parametri di connessione
*/
// nome di host
$host = "localhost";
// nome del database
$db = "nominativi";
// username dell'utente in connessione
$user = "mrwebmaster";
// password dell'utente
$password = "...";

/*
  blocco try/catch di gestione delle eccezioni
*/
try {
  // stringa di connessione al DBMS
  $connessione = new PDO("mysql:host=$host;dbname=$db", $user, $password);
  // imposto dell'attributo necessario per ottenere il report degli errori
  $connessione->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  // selezione e visualizzazione dei dati estratti
  foreach ($connessione->query("SELECT nome, cognome FROM contatti") as $row)
  {
    echo $row['nome'] ." ". $row['cognome'] . "<br />";
  }
  // chiusura della connessione
  $connessione = null;
}
catch(PDOException $e)
{
  // notifica in caso di errore nel tentativo di connessione
  echo $e->getMessage();
}
?>

Anche in questo caso si parte con la definizione dei parametri di connessione utilizzati poi per la creazione dell’handle ($connessione) tramite l’istanza dell’oggetto PDO; tale handle viene poi utilizzato per la chiamata a due metodi differenti:

  • setAttribute() che nel caso specifico è stato utilizzato per gestire eventuali eccezioni all’interno del blocco try/catch specificando l’attributo PDO::ATTR_ERRMODE ed il valore PDO::ERRMODE_EXCEPTION;
  • query() che accetta come parametro l’istruzione SQL da lanciare.

Il metodo query() si occupa anche dell’esecuzione di tale istruzione generando in output un set di risultati sotto forma di oggetto (PDOStatement object); per poter visualizzare il contenuto di quest’ultimo è possibile manipolarlo come un vettore iterabile (rowset) da ciclare attraverso un comune loop basato su foreach().

Nel caso specifico dell’esempio proposto, ogni iterazione del rowset ottenuto tramite la query è stata messa in relazione all’array $row i cui valori divengono stampabili richiamando i rispettivi indici associativi, questi ultimi sono poi anche i nomi dei campi scelti per l’estrazione dei dati nell’istruzione SQL:

foreach ($connessione->query("SELECT nome,cognome FROM contatti") as $row)
{
  echo $row['nome'] ." ". $row['cognome'] . "<br />";
}

L’estensione PDO, è bene precisarlo, mette a disposizione anche un altro metodo per effettuare le operazioni di estrazione dei record, si tratta del metodo fetch() che verrà descritto di seguito.

Il metodo fetch()

Come visto qui sopra, per l’esecuzione delle query PDO genera istanze della classe PDOStatement, quest’ultima gestisce i risultati ottenuti con le istruzioni effettuate mentre PDOException (utilizzato nel nostro caso all’interno del blocco try/catch) si fa carico delle eventuali eccezioni; il metodo query() restituisce quindi un set di risultati sotto forma di un oggetto della classe PDOStatement, tale oggetto potrà essere poi associato ad un array iterabile tramite ciclo foreach per il recupero dei dati estratti.

Una prima metodologia alternativa (ma non meno corretta) per il recupero di questi dati potrebbe essere basata sul metodo fetch(), come nell’esempio seguente:

// estrazione di record con il metodo fetch
$query = $connessione->query("SELECT nome, cognome FROM contatti");
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
  echo $row['nome'] ." ". $row['cognome'] . "<br />";
}

Nello specifico tale metodo recupera un record da un set di risultati associato ad un oggetto PDOStatement; il metodo accetta un parametro, detto fetch_style, che a sua volta determinerà le modalità di restituzione del record recuperato da parte di PDO. Il valore predefinito del fetch_style è uguale a PDO::FETCH_BOTH che consente di ottenere un array nel quale ogni elemento costitutivo è presente sia con chiave letterale (i nomi dei campi) che numerica (un indice da "0" a "n"); PDO::FETCH_ASSOC è invece un parametro più specifico che restituisce un array indicizzato tramite i nomi dei campi presenti in tabella.

Da notare come, nell’esempio proposto, tale array sia stato ciclato tramite un’istruzione basata su while (che proseguirà nella sua iterazione sino a quando il recordset non sarà stato "svuotato"), mentre il codice da iterare sarà quello della stampa a video dei dati recuperati.

Da segnalare come il medesimo risultato dell’esempio visto qui sopra avrebbe potuto raggiungersi anche in questo modo:

// estrazione di record con il metodo setFetchMode
$query = $connessione->query("SELECT nome, cognome FROM contatti");
$query->setFetchMode(PDO::FETCH_ASSOC);
while($row = $query->fetch()){
  echo $row['nome'] ." ". $row['cognome'] . "<br />";
}

setFetchMode() ha in pratica il compito di impostare la modalità, "mode", di recupero dei dati per l’istruzione SELECT passata al metodo query(); nel caso del nostro esempio il "mode" scelto sarà il già noto PDO::FETCH_ASSOC, mentre il metodo fetch() consentirà di ottenere i valori da recuperare tramite la loro associazione ad un array nel ciclo while.

Gestire le query in modo sicuro

Nel caso in cui si operi con query generate dinamicamente, ad esempio mediante l’inclusione di parametri generati da input degli utenti (ad esempio attraverso un form o una querystring) è consigliabile fare ricorso al metodo quote() per effettuare l’escape dei parametri, come accade nell’esempio seguente dove l’istruzione SQL prevede l’adozione della clausola WHERE, per rendere più precisi i risultati delle query, recuperando da un form una stringa da ricerare all’interno di uno specifico campo della nostra tabella:

// quoting del parametro passato alla clausola WHERE
$sql = "SELECT cognome FROM contatti WHERE nome = '". $connessione->quote($_POST['nome']) . "'"; 
foreach ($connessione->query($sql) as $row)
{
  echo $row['nome'] ." ". $row['cognome'] . "<br />";
}

In questo modo sarà possibile garantire una maggiore protezione da tentativi di attacco come per esempio quelli basati sulla SQL Injection; PDO offre però strumenti ancora più avanzati per la protezione contro azioni malevole che verranno analizzati a breve.

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.