17 filtrare i dati con PDO

Il metodo presentato precedentemente, oltre che altamente scomodo, risulta essere anche particolarmente insicuro, infatti è passibile di SQL injection, pensate aggiungere

http://127.0.0.1:8000/albums?id=2&album_name="pippo" or 1=1

In questo caso un utente potrebbe passarci un parametro del genere via GET e avrebbe accesso a tutti i dati, pensate solo ad un login, mostreremmo tutte le credenziali perchè la query 1=1 risulta TRUE.

Riformuliamo il codice utilizzando i PDO

Metodo coi segnaposti

Intanto inizializziamo la $where come array vuoto, poi lasciamo la condizione $request->has(‘id’) e il suo valore lo inseriamo nell’array $where inserendo anche la chiave id

public function index(Request $request)
{
 $sql = 'select * from albums';
 $where = [];

 if($request->has('id')) {
  $where['id'] = $request->get('id');
 }

Stessa cosa facciamo se c’è anche album_name

if($request->has('album_name')) {
 $where['album_name'] = $request->get('album_name');
}

ora modifichiamo $sql aggiungendo WHERE 1=1

$sql = 'select * from albums WHERE 1=1';

adesso molto semplicemente nell’if dell’id concateniamo un AND id=? dove il punto di domanda è il nostro segna posto

$sql .= ' AND id=?';

stessa cos per album_name

if($request->has('album_name')) {
 $where['album_name'] = $request->get('album_name');
 $sql .= ' AND album_name=?';
}

Adesso al metodo select() della nostra facade DB passiamo anche i valori dell’array $where.

Per passare solo i valori di un array senza le chiavi usiamo il metodo php array_values()

return DB::select($sql, array_values($where));

Passando i parametri in questo modo, la SQL injection non funzionerà, perchè i valori vengono passati tramite l’array $where che li prende dai segna posti e non inseriti nel comando SQL in una variabile

Metodo per riferimento

è molto simile al precedente, solo che invece che usare il punto di domanda si usano i due punti seduiti dal nome della chiave che riceve il dato

$sql .= ' AND id=:id';
$sql .= ' AND album_name=:album_name';

a questo punto a DB::select() passiamo anche le chiavi, quindi rimuoviamo la funzione array_values().

public function index(Request $request)
{
$sql = 'select * from albums WHERE 1=1';
$where = [];

if($request->has('id')) {
$where['id'] = $request->get('id');
$sql .= " AND id=:id";
}

if($request->has('album_name')) {
$where['album_name'] = $request->get('album_name');
$sql .= " AND album_name=:album_name";
}

//dd($sql);
return DB::select($sql, $where);
}

Come abbiamo visto questi metodi con i PDO oltre che più sicuri sono anche più semplici da costruire.