1.1 Costruttori e metodi PDO PHP5

Posted: 29th marzo 2010 by info in Sqlite

[setAttribute] – http://it.php.net/manual/en/pdo.setattribute.php

Con il comando  setAttribute e’ possibile settare le impostazioni del nostro oggetto PDO, ad esempio specificando se l’ autocommit deve essere attivo ( default ) o disattivo cosi’ da poter fare rollBacks in qualunque momento.
Esempio:
$mypdo→setAttribute();
$mypdo->setAttribute(ATTRIBUTO_PDO, $valore_generico);

ATTRIBUTO_PDO e’ un attributo dedicato pdo, altri sono quelli che si possono leggere con PDO::getAttribute()
Altro esempio:

$mypdo->setAttribute(PDO_ATTR_AUTOCOMMIT, 0);
echo (string) $mypdo->getAttribute(PDO_ATTR_AUTOCOMMIT);
// sara’ 0 quindi l’ autocommit e’ disabilitato

NOTA: come e’ per il getAttribute, il setAttribute non ha valori universali, i parametri devono essere supportati dal tipo di database che stiamo utilizzando.

[PDOStatement::execute] – http://it.php.net/manual/en/pdostatement.execute.php

Abbiamo visto il metodo prepare per usare query sicure ma siamo rimasti ad un punto morto … cosa me ne faccio di prepare se poi la query non ha senso ? Infatti tale metodo restituisce una variabile / oggetto in grado di effettuare le modifiche necessarie per eseguire la query. Primo esempio:

Esempio con dati inseriti manualmente:
// preparo la query
$stpdo = $mypdo->prepare(’UPDATE mytable SET user = “pippo” WHERE id > 10′);
// eseguo la query
$stpdo->execute();

Esempio con variabili nella query:
// preparo la query
$stpdo = $mypdo->prepare(’UPDATE mytable SET user = ? WHERE id > ?’);
$stpdo->execute(array(’pippo’, 10));

Execute puo’ ricevere come parametro un array contenente le informazioni da sostituire ai punti di domanda.
Quando utilizziamo i punti di domanda l’ ordine con cui inviare i parametri ad execute e’ fondamentale ed e’ esattamente da sinistra a destra.
Una cosa da notare e’ la mancanza di →quote o di escaping della stringa pippo … 
Non serve poiche’ se ne occupa la classe. Questa sapra’ che al primo punto di domanda della query ci deve essere esattamente la stringa contenuta nel primo parametro dell’ array passato quindi anche se questo dovesse contenere chissacosa, non sara’ possibile tentare sql injections piu’ comuni perche’ il valore verra’ trattato esattamente come stringa tra apici e non come testo su una query.
Idem per il secondo punto di domanda,ovvio che se al posto di un intero passiamo una stringa la query non andra’ a buon fine ma comunque non ci saranno risultati inaspettati.

Esempio piu’ leggibile:
// preparo la query
$stpdo = $mypdo->prepare(’UPDATE mytable SET user = :user WHERE id > :id’);
$stpdo->execute(array(’:user’=>’pippo’, ‘:id’=>10));
$stpdo->execute(array(’:id’=>10, ‘:user’=>’pluto’));

L’ esempio mostrato precedentemente funziona alla perfezione e il risultato sara’ quello del secondo execute, visto che e’ un update. Ma se avessimo bisogno di tanti insert, di diverse select o di altre query dove la sintassi e’ identica ma i valori cambiano ( id, nomi, quello che vi pare ) sara’ possibile evitare di rifare il prepare ed utilizzare quello gia’ dichiarato in fase di assegnazione / creazione dello Statement.

$stpdo = $mypdo->prepare(’UPDATE mytable SET user = :user WHERE id > :id’);
$stpdo->execute(array(’:user’=>’pippo’, ‘:id’=>1));
$stpdo->execute(array(’:user’=>’pluto’, ‘:id’=>5));
$stpdo->execute(array(’:user’=>’paperino’, ‘:id’=>10));
$stpdo->execute(array(’:user’=>’topolino’, ‘:id’=>15));
$stpdo->execute(array(’:user’=>’cip’, ‘:id’=>20));
$stpdo->execute(array(’:user’=>’ciop’, ‘:id’=>25));
$stpdo->execute(array(’:user’=>’ziopaperone’, ‘:id’=>30));
// … e cosi’ via …

Inoltre le prestazioni sono veramente elevate perche’ viene sfruttato un sistema interno di caching da parte del prepare. A questo statement  torna un valore di tipo booleano che ci permette di sapere se la query e’ stata eseguita con successo oppure no.

if( $stpdo->execute() ) // … OK, query eseguita con successo

[PDOStatement::bindParam] – http://it.php.net/manual/en/pdostatement.bindparam.php

Se con execute possiamo lavorare tranquilli in inserimento dati, con bindParam possiamo anche stare tranquilli sul tipo di dato utilizzato in input o output durante le stored procedures.

Sintassi:
bool PDOStatement::bindParam ( mixed parameter, mixed &variable [, int data_type [, int length]] )
Mixed parameter e’ un numero intero se utilizziamo il punto interrogativo, altrimenti una stringa se utilizziamo il metodo piu’ leggibile.
Mixed &variable e’ una variabile passata per riferimento con il contenuto che deve sostituire il valore descritto nel primo parametro.

Esempio1:
$calories = 150;
$colour = ‘red’;
$sth = $dbh->prepare(’SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour’);
$sth->bindParam(’:calories’, $calories, PDO::PARAM_INT);
$sth->bindParam(’:colour’, $colour, PDO::PARAM_STR, 12);
$sth->execute(); 

Esempio2:
$calories = 150;
$colour = ‘red’;
$sth = $dbh->prepare(’SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?’);
$sth->bindParam(1, $calories, PDO::PARAM_INT);
$sth->bindParam(2, $colour, PDO::PARAM_STR, 12);
$sth->execute();

Per i soli input e’ consigliato nel sito stesso di php.net di utilizzare execute e l’ array per l’ execute.
Cerchiamo di capire meglio dov’e’ che bindParam fa la differenza … e cominciamo con il terzo parametro opzionale, il data_type.
Questo specifica il tipo di dato in input o output all’ interno della stored procedures e puo’ essere piu’ di uno grazie all’ operatore di bitwise | .
In caso di parametro da usare in output e’ necessario specificare il quarto parametro ovvero la length.

[PDOStatement::bindColumn] – http://it.php.net/manual/en/pdostatement.bindcolumn.php

In pratica si tratta di specificare prima come devono chiamarsi i dati letti da una query e di che tipo devono essere. Sintassi:

bool PDOStatement::bindColumn ( mixed column, mixed &param [, int type [, int maxlen [, mixed driver_options]]] )

Mixed column e’ il numero della colonna restituita dalla query.
Mixed &param e’ la variabile contenente il valore restituito.
Il primo e piu’ semplice esempio che mi viene in mente e’ il seguente:

// preparo la query
$stpdo = $mypdo->prepare(’SHOW TABLES’);
// preparo il risultato
$stpdo->bindColumn(1, $table_name);
// eseguo la query
$stpdo->execute();
// eseguo il loop sul risultato per avere tutti i nomi delle tabelle
while($row = $stpdo->fetch(PDO_FETCH_BOUND))
 echo $table_name.’<br />’; // stampo i nomi

La variabile $table_name anche se inesistente viene popolata e inizializzata automaticamente all’ interno della chiamata a bindColumn.
La stessa variabile viene automaticamente riassegnata ad ogni ciclo del while , permettendoci di evitare i soliti $row[N] per il fetch_row o $row['key'] per il fetch_assoc.

$stpdo = $mypdo->prepare(’SELECT id, user FROM mytable’);
$stpdo->bindColumn(1, $id, PDO_PARAM_INT);
$stpdo->bindColumn(2, $user, PDO_PARAM_STR);
$stpdo->execute();
while($row = $stpdo->fetch(PDO_FETCH_BOUND))
echo “{$id} => {$user}<br />”;

[PDOStatement::fetch] – http://it.php.net/manual/en/pdostatement.fetch.php

while($stpdo->fetch(PDO_FETCH_BOUND))
 echo “{$id} => {$user}<br />”;

Stesso risultato, infatti il “$row =” in questo caso non serve proprio perche’ usiamo il parametro PDO_FETCH_BOUND che si basa sui vari bindColumn precedentemente dichiarati. Ma non e’ detto che ogni volta si debba usare il comodo bindColumn, no ? E infatti il row potrebbe esserci utile con altri parametri da specificare nel fetch, ovvero:

PDO_FETCH_ASSOC  #usatelo come mysql_fetch_assoc
PDO_FETCH_BOTH   #usatelo come mysql fetch_array, risultato duplicato, quello di default
PDO_FETCH_BOUND  #usatelo come da esempio per il bindColumn
PDO_FETCH_LAZY  #combina *_BOTH e *_OBJ , l’ ammazza prestazioni , imho …
PDO_FETCH_OBJ  #ritorna un oggetto con le proprieta’ che hanno il nome dei campi, interessante
PDO_FETCH_NUM  #il mio preferito ovviamente …. analogo a mysql_fetch_row

Alcuni esempi basati sulla query precedente:

// *_NUM
while($row = $stpdo->fetch(PDO_FETCH_NUM))
  echo “{$row['0']} => {$row['1']}<br />”;
 
// *_ASSOC
while($row = $stpdo->fetch(PDO_FETCH_ASSOC))
  echo “{$row['id']} => {$row['user']}<br />”;
 
// *_OBJ
while($row = $stpdo->fetch(PDO_FETCH_OBJ))
  echo “{$row->id} => {$row->user}<br />”;

 

[PDOStatement::setFetchMode] – http://it.php.net/manual/en/pdostatement.setfetchmode.php

Setta il tipo di fetch da utilizzare di default con , appunto, fetch.

bool PDOStatement::setFetchMode ( int mode )

int mode e’ una variabile del tipo gia’ visto per i metodi di fetch, il risultato e’ true se l’ operazione e’ avvenuta con successo, false in caso di insuccesso.
$stpdo = $mypdo->prepare(’SELECT id, user FROM mytable’);
$stpdo->setFetchMode(PDO_FETCH_NUM);
$stpdo->execute();
while($row = $stpdo->fetch())
 echo “{$row[0]} => {$row[1]}<br />”;

[PDOStatement::rowCount] – http://it.php.net/manual/en/pdostatement.rowcount.php

Restituisce semplicemente il numero di righe affette dall’ ultima query di tipo INSERT, DELETE o UPDATE.

// eseguo una query del tipo
// UPDATE mytable SET user = ‘pippo’ WHERE id > 3
$stpdo->execute();
echo (string) $stpdo->rowCount();

PDOStatement::columnCount – http://it.php.net/manual/en/pdostatement.columncount.php

Restituisce il numero di colonne presenti nel risultato della query.
Esempio:

$stpdo = $mypdo->prepare(’SELECT id, user FROM mytable’);
$stpdo->execute();
echo (string) $stpdo->columnCount(); // 2, poiche’ tornano id e user

[PDOStatement::errorCode] – http://it.php.net/manual/en/pdostatement.errorcode.php
PDOStatement::errorInfo] – http://it.php.net/manual/en/pdostatement.errorinfo.php

Si comportano allo stesso modo dei metodi per l’ oggetto PDO. Esempio di applicazione:

if($stpdo->execute())
 var_dump($stpdo->fetchAll());
else
 echo ‘Errore: ‘.$stpdo->errorCode();
 
// Oppure sull’ else …
 
else {
 $error = $stpdo->errorInfo();
 echo $error[2]; // il piu’ utile
}