Introduzione
Quando si lavora con PDO in PHP, una delle operazioni più frequenti è leggere i dati dal database e trasformarli in una struttura facile da usare nel codice. Molti sviluppatori si concentrano solo sulla query SQL, ma trascurano un aspetto fondamentale: il fetch mode, cioè il modo in cui PDO restituisce i risultati.
Questo sotto-argomento è molto utile perché incide direttamente su leggibilità, manutenzione e qualità del codice. Se scegli il fetch mode corretto, puoi ottenere array associativi, oggetti, valori singoli o strutture personalizzate senza dover fare trasformazioni inutili dopo la query.
In questo tutorial vedremo come usare in modo pratico i principali fetch mode di PDO, con un esempio reale basato su una tabella products. L’obiettivo è capire come leggere i dati nel formato più adatto al contesto, evitando codice confuso o ripetitivo.
Codice completo
<?php
declare(strict_types=1);
/**
* Esempio: lettura dati da database con diversi fetch mode PDO
* Scenario: tabella products con campi:
* - id
* - name
* - price
* - created_at
*/
$dsn = ´mysql:host=localhost;dbname=shop;charset=utf8mb4´;
$user = ´root´;
$password = ´´;
try {
// Connessione PDO con opzioni consigliate
$pdo = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
// 1) FETCH_ASSOC: array associativo
$stmt = $pdo->prepare(´SELECT id, name, price, created_at FROM products ORDER BY created_at DESC´);
$stmt->execute();
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "<h3>Lista prodotti (FETCH_ASSOC)</h3>";
echo "<pre>";
print_r($products);
echo "</pre>";
// 2) FETCH_OBJ: ogni riga diventa un oggetto stdClass
$stmt = $pdo->prepare(´SELECT id, name, price, created_at FROM products ORDER BY created_at DESC´);
$stmt->execute();
$productObjects = $stmt->fetchAll(PDO::FETCH_OBJ);
echo "<h3>Lista prodotti (FETCH_OBJ)</h3>";
echo "<pre>";
print_r($productObjects);
echo "</pre>";
// 3) FETCH_COLUMN: estrarre una sola colonna
$stmt = $pdo->prepare(´SELECT name FROM products ORDER BY name ASC´);
$stmt->execute();
$productNames = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo "<h3>Nomi prodotti (FETCH_COLUMN)</h3>";
echo "<pre>";
print_r($productNames);
echo "</pre>";
// 4) fetch() singola riga: utile per dettagli di un record
$productId = 3;
$stmt = $pdo->prepare(´SELECT id, name, price, created_at FROM products WHERE id = :id´);
$stmt->execute([´id´ => $productId]);
$singleProduct = $stmt->fetch(PDO::FETCH_ASSOC);
echo "<h3>Prodotto singolo (fetch su una riga)</h3>";
echo "<pre>";
print_r($singleProduct);
echo "</pre>";
// 5) FETCH_KEY_PAIR: crea un array chiave => valore
$stmt = $pdo->query(´SELECT id, name FROM products ORDER BY id ASC´);
$productMap = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
echo "<h3>Mappa ID => nome prodotto (FETCH_KEY_PAIR)</h3>";
echo "<pre>";
print_r($productMap);
echo "</pre>";
} catch (PDOException $e) {
// In produzione, meglio loggare l´errore invece di mostrarlo all´utente
echo "Errore di connessione o query: " . $e->getMessage();
}
Spiegazione
Il codice mostra come ottenere lo stesso tipo di dato in formati diversi, a seconda delle necessità. Questo è un punto importante: non esiste un fetch mode migliore in assoluto, ma esiste quello più adatto al problema che stai risolvendo.
1. FETCH_ASSOC
È uno dei metodi più usati. Ogni riga viene restituita come array associativo, con i nomi delle colonne come chiavi. Per esempio:
- $product[´name´]
- $product[´price´]
Questo formato è molto comodo quando devi passare i dati a una view, a un template o a un JSON response.
2. FETCH_OBJ
Con FETCH_OBJ, ogni riga diventa un oggetto standard di PHP. I campi si leggono con la sintassi a oggetto:
- $product->name
- $product->price
Può risultare più leggibile in alcuni contesti, soprattutto quando il progetto usa un approccio orientato agli oggetti. Tuttavia, se devi modificare o serializzare i dati, l’array associativo spesso è più pratico.
3. FETCH_COLUMN
Questo fetch mode è perfetto quando ti serve una sola colonna, ad esempio una lista di nomi, email o ID. Invece di ricevere un array di array, ottieni direttamente un array semplice:
- ["Mouse", "Monitor", "Tastiera"]
È una soluzione elegante per menu, select HTML o controlli rapidi sui valori presenti nel database.
4. fetch() per una singola riga
Se la query deve restituire un solo record, usare fetch() è la scelta più corretta. In questo caso non serve fare fetchAll(), perché non stai aspettando una lista ma un solo elemento.
Questo migliora sia la chiarezza del codice sia l’efficienza, perché eviti di caricare dati inutili in memoria.
5. FETCH_KEY_PAIR
Questo fetch mode è molto utile quando vuoi costruire una mappa del tipo chiave => valore. Nel nostro esempio, la query seleziona due colonne:
- id come chiave
- name come valore
Il risultato diventa un array semplice da usare, ad esempio per popolare un elenco di riferimento o una cache temporanea in memoria.
Un dettaglio importante: i fetch mode richiedono che la query restituisca i dati nel formato giusto. Se usi FETCH_KEY_PAIR, la query deve selezionare esattamente due colonne. Se usi FETCH_COLUMN, la logica è simile: ti serve una sola colonna utile.
Best practice
- Imposta un default fetch mode nella connessione PDO, così il comportamento sarà coerente in tutto il progetto.
- Usa FETCH_ASSOC come scelta di base: è leggibile, prevedibile e facile da serializzare.
- Usa fetch() quando ti aspetti un solo record. Evita fetchAll() se non serve.
- Evita trasformazioni inutili: scegli direttamente il formato più adatto alla tua esigenza.
- Non mischiare stili diversi senza motivo: se un modulo usa array associativi, cerca di mantenere lo stesso approccio nel resto del codice.
- Disattiva l’emulazione dei prepared statement quando possibile, per un comportamento più vicino al driver reale del database.
- Gestisci sempre le eccezioni con try/catch e non mostrare dettagli sensibili in produzione.
Riepilogo
Il fetch mode di PDO è un dettaglio tecnico che fa una grande differenza nella qualità del codice. Saper scegliere tra FETCH_ASSOC, FETCH_OBJ, FETCH_COLUMN, FETCH_KEY_PAIR e fetch() ti permette di scrivere query più pulite e di ottenere dati già pronti per l’uso.
In pratica:
- usa FETCH_ASSOC per la maggior parte dei casi;
- usa FETCH_OBJ se preferisci accesso a oggetti;
- usa FETCH_COLUMN per liste semplici;
- usa FETCH_KEY_PAIR per mappe chiave-valore;
- usa fetch() per un singolo record.
Se impari a sfruttare bene questi strumenti, il tuo codice PDO sarà più pulito, più leggibile e più facile da mantenere nel tempo.
Approfondisci con risorse ufficiali
- Documentazione ufficiale PHP su PDO: https://www.php.net/manual/it/book.pdo.php
- PDOStatement::fetch(): https://www.php.net/manual/it/pdostatement.fetch.php
- PDOStatement::fetchAll(): https://www.php.net/manual/it/pdostatement.fetchall.php
- PDO fetch modes: https://www.php.net/manual/it/pdo.constants.fetch-modes.php
- PDO::setAttribute(): https://www.php.net/manual/it/pdo.setattribute.php
