<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blogbonzo: Matteo Magni &#187; Pgsql</title>
	<atom:link href="http://blog.ilbonzo.org/category/database/pgsql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ilbonzo.org</link>
	<description>Consulente Informatico, Web Developer &#38; System Administrator</description>
	<lastBuildDate>Wed, 09 Dec 2009 13:07:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PDO, Abstraction Layer</title>
		<link>http://blog.ilbonzo.org/2008/06/16/pdo-abstraction-layer/</link>
		<comments>http://blog.ilbonzo.org/2008/06/16/pdo-abstraction-layer/#comments</comments>
		<pubDate>Mon, 16 Jun 2008 14:19:42 +0000</pubDate>
		<dc:creator>Bonzo</dc:creator>
				<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Pgsql]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.ilbonzo.org/2008/06/16/pdo-abstraction-layer/</guid>
		<description><![CDATA[Finalmente con la versione 5.1 PHP ha un nuovo livello di astrazione per la connettività con i database veramente valido.
PDO, PHP Data Objects
Ho deciso di studiarlo un po&#8217;:
Creo un Database di prova:

DROP TABLE IF EXISTS first_table;


--CREATE TABLE first_table (
--id INT(10) NOT NULL AUTO_INCREMENT,
--name VARCHAR(255) NOT NULL,
--surname VARCHAR(255) NOT NULL,
--PRIMARY KEY (id)
--) TYPE=MyISAM;


CREATE TABLE first_table (
id [...]]]></description>
			<content:encoded><![CDATA[<p>Finalmente con la versione 5.1 PHP ha un nuovo livello di astrazione per la connettività con i database veramente valido.<br />
<strong><a href="http://it2.php.net/pdo">PDO</a>, PHP Data Objects</strong></p>
<p>Ho deciso di studiarlo un po&#8217;:</p>
<p>Creo un Database di prova:<br />
<code><br />
DROP TABLE IF EXISTS first_table;<br />
</code><br />
<code><br />
--CREATE TABLE first_table (<br />
--id INT(10) NOT NULL AUTO_INCREMENT,<br />
--name VARCHAR(255) NOT NULL,<br />
--surname VARCHAR(255) NOT NULL,<br />
--PRIMARY KEY (id)<br />
--) TYPE=MyISAM;<br />
</code><br />
<code><br />
CREATE TABLE first_table (<br />
id INT(10) NOT NULL AUTO_INCREMENT,<br />
name VARCHAR(255) NOT NULL,<br />
surname VARCHAR(255) NOT NULL,<br />
PRIMARY KEY (id)<br />
) TYPE=innoDB;<br />
</code><br />
<code><br />
INSERT INTO first_table (name,surname) VALUES ('matteo','magni');<br />
INSERT INTO first_table (name,surname) VALUES ('john','starks');<br />
INSERT INTO first_table (name,surname) VALUES ('michael','jordan');<br />
INSERT INTO first_table (name,surname) VALUES ('kobe','bryant');<br />
INSERT INTO first_table (name,surname) VALUES ('earvin','johnson');<br />
INSERT INTO first_table (name,surname) VALUES ('larry','bird');<br />
INSERT INTO first_table (name,surname) VALUES ('patrick','ewing');<br />
INSERT INTO first_table (name,surname) VALUES ('reggie','miller');<br />
INSERT INTO first_table (name,surname) VALUES ('ron','harper');<br />
INSERT INTO first_table (name,surname) VALUES ('anfernee','hardaway');<br />
INSERT INTO first_table (name,surname) VALUES ('tim','hardaway');<br />
INSERT INTO first_table (name,surname) VALUES ('mitch','richmond');<br />
INSERT INTO first_table (name,surname) VALUES ('jason','williams');<br />
INSERT INTO first_table (name,surname) VALUES ('allen','iverson');<br />
INSERT INTO first_table (name,surname) VALUES ('dwayne','wade');<br />
</code></p>
<p>Lo importo così dopo aver creato il DB pdo<br />
<code><br />
mysql -p -D pdo < pdo.sql<br />
</code><br />
Per le prove utilizzerò sia la versione con tabella MyISAM che quella con tabella InnoDB, la differenza è che per la prima non sono disponibili le transazioni.</p>
<p><strong>Usiamo le eccezioni per connetterci al DB</strong><br />
</code><code><br />
//USO le eccezioni<br />
$string_dsn = 'mysql:host=localhost;dbname=pdo'; // mysql<br />
$string_username = 'user';<br />
$string_password = 'password';<br />
try {<br />
    $mypdo = new PDO($string_dsn, $string_username, $string_password);<br />
}<br />
catch(PDOException $e) {<br />
    echo 'Errore di connessione: '.$e->getMessage();<br />
}<br />
</code></p>
<p>Query fatta con errore, mi restituisce il numero dell&#8217;errore:<br />
<code><br />
$mypdo->exec('SELECT * FROM SELECT'); // errore generato appositamente<br />
echo 'Errore N: '.$mypdo->errorCode();<br />
</code>    </p>
<p>Se la uso così è molto utile, mando io il messaggio che voglio:<br />
<code><br />
if($mypdo->errorCode() !== '' || !$mypdo->exec('SELECT * FROM SELECT'))<br />
    echo 'errore nella query SELECT * FROM SELECT';<br />
</code></p>
<p>Così mi ritorna un array di tre elementi con le notizie sull&#8217;errore:<br />
<code><br />
var_dump($mypdo->errorInfo());<br />
//array di tre elementi<br />
if(count($mypdo->errorInfo()) == 1) // ... tutto ok<br />
if(count($mypdo->errorInfo()) > 1) { // ... ci sono errori<br />
    $errorinfo = $mypdo->errorInfo();<br />
    echo $errorinfo[2]; // stringa con l' errore<br />
}<br />
</code></p>
<p><strong>QUERY</strong> semplice senza preparare niente,<br />
Mi ritorna i dati accessibili sia con il numero della colonna (partendo da 0) che con il nome della colonna<br />
Query senza parametri aggiuntivi per stabilire che Fetch usare:</p>
<p><code><br />
foreach($mypdo->query('SELECT * FROM first_table') as $row)<br />
{<br />
    echo '--------------&lt;br /&gt;';<br />
    echo '1: '.$row[0].' - 2: '.$row[1].'&lt;br /&gt;';<br />
    echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
</code><br />
mi ritorna i dati accessibili sia con il numero della colonna (partendo da 0) che con il nome della colonna.</p>
<p>Esplicito il tipo di Fetch con il parametro PDO_FETCH_*<br />
<strong>PDo::FETCH_BOTH</strong> #usatelo come mysql fetch_array, risultato duplicato, quello di default<br />
<code><br />
foreach($mypdo->query('SELECT * FROM first_table', PDO::FETCH_BOTH) as $row)<br />
{<br />
    echo '--------------&lt;br /&gt;';<br />
    echo '1: '.$row[0].' - 2: '.$row[1].'&lt;br /&gt;';<br />
    echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
</code></p>
<p><strong>PDO::FETCH_ASSOC</strong> #usatelo come mysql_fetch_assoc<br />
<code><br />
foreach($mypdo->query('SELECT * FROM first_table', PDO::FETCH_ASSOC) as $row)<br />
{<br />
    echo '--------------&lt;br /&gt;';<br />
    echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
</code></p>
<p><strong>PDO::FETCH_NUM </strong>#analogo a mysql_fetch_row<br />
<code><br />
foreach($mypdo->query('SELECT * FROM first_table', PDO::FETCH_NUM) as $row)<br />
{<br />
    echo '--------------&lt;br/&gt;';<br />
    echo '1: '.$row[0].' - 2: '.$row[1].'&lt;br/&gt;';<br />
}<br />
</code></p>
<p><strong>PDO::FETCH_OBJ </strong>#ritorna un oggetto con le proprieta&#8217; che hanno il nome dei campi<br />
<code><br />
foreach($mypdo->query('SELECT * FROM first_table', PDO::FETCH_OBJ) as $row)<br />
{<br />
    echo '--------------&lt;br /&gt;';<br />
    echo 'id->'.$row->id.' - name-> '.$row->name.'&lt;br /&gt;';<br />
}<br />
</code></p>
<p><strong>PDO::FETCH_LAZY </strong>#combina *_BOTH e *_OBJ<br />
<code><br />
foreach($mypdo->query('SELECT * FROM first_table', PDO::FETCH_LAZY) as $row)<br />
{<br />
    echo '--------------&lt;br /&gt;';<br />
    echo '1: '.$row[0].' - 2: '.$row[1].'&lt;br /&gt;';<br />
    echo 'id:  '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
    echo 'id->'.$row->id.' - name-> '.$row->name.'&lt;br /&gt;';<br />
}<br />
</code></p>
<p><strong>PDO::FETCH_BOUND</strong> #Lo vediamo con bindColumn,<br />
restituiti come attributi alle variabili PHP</p>
<p>Per Evitare problemi con DB case sensitive e non case sensitive<br />
Setto che i nomi delle colonne siano restituiti sempre minuscoli<br />
<code><br />
$mypdo->setAttribute(PDO::CASE_LOWER);<br />
/*<br />
 * Psso usare anche<br />
 * PDO::CASE_UPPER<br />
 * PDO::CASE_NATURAL come sono fornite dal driver, metodo di default<br />
 */<br />
</code><br />
oppure si usa sempre FETCH_NUM</p>
<p><strong>Utilizzo delle Transazioni</strong></p>
<p>inizio la transazione</p>
<p>Su Mysql devo usare tabelle InnoDB perchè MyIsam non supportano le transazioni</p>
<p>Però&#8230;<br />
The following example begins a transaction and issues two statements that<br />
modify the database before rolling back the changes.<br />
On MySQL, however, the DROP TABLE statement automatically commits the<br />
transaction so that none of the changes in the transaction are rolled back.</p>
<p>Quindi niente drop per una transazione.<br />
<code><br />
$mypdo->beginTransaction();<br />
$mypdo->exec('DROP TABLE first_table');<br />
$mypdo->rollBack(); // la tabella mytable rimarra' invariata :-)<br />
</code></p>
<p>come detto su MySQL la cancella lo stesso.</p>
<p><code><br />
$mypdo->beginTransaction();<br />
$mypdo->exec("INSERT INTO first_table (name,surname) VALUES ('gianni','morandi')");<br />
$mypdo->rollBack(); // la tabella mytable rimarra' invariata :-)<br />
</code></p>
<p><code><br />
$mypdo->beginTransaction();<br />
$mypdo->exec("INSERT INTO first_table (name,surname) VALUES ('gianni','morandi')");<br />
$mypdo->commit(); // la tabella mytable rimarra' invariata :-)<br />
</code><br />
mi inserisce il nuovo valore.</p>
<h3>Prepared Statement</h3>
<p><strong>Metodo Fetch</strong><br />
Metodo implementato nello statement che è in grado di spostare il cursore dei risultati di una query in un ciclo.<br />
Gli posso passare i parametri come a query.<br />
/*<br />
 * PDO::FETCH_ASSOC, PDO::FETCH_BOTH, PDO::FETCH_BOUND, PDO::FETCH_LAZY,<br />
 * PDO::FETCH_OBJ, PDO::FETCH_NUM<br />
 */<br />
<code><br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare('UPDATE first_table SET name = "pippo" WHERE id = 17');<br />
// eseguo la query<br />
$stpdo->execute();<br />
$mypdo->commit();<br />
echo 'SELECT';<br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare('SELECT * FROM first_table');<br />
// eseguo la query<br />
$stpdo->execute();<br />
//stampo a video il contenuto dell'array che mi crea fetch<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$mypdo->commit();<br />
</code></p>
<p><strong>La potenza prepare e execute </strong><br />
Potenza del metodo prepare<br />
<code><br />
$mypdo->beginTransaction();<br />
$stpdo = $mypdo->prepare('UPDATE first_table SET name = ? WHERE id = ?');<br />
//i punti interrogativi saranno sostituiti da execute<br />
$stpdo->execute(array('gianni', 17));<br />
$mypdo->commit();<br />
echo 'SELECT';<br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare('SELECT * FROM first_table');<br />
// eseguo la query<br />
$stpdo->execute();<br />
//stampo a video il contenuto dell'array che mi crea fetch<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$mypdo->commit();<br />
</code><br />
Posso preparare la query una volta e fare poi i vari inserimenti.<br />
<strong>potenza prepare e execute ancora</strong><br />
<code><br />
$mypdo->beginTransaction();<br />
$stpdo = $mypdo->prepare('UPDATE first_table SET name = :name WHERE id = :id');<br />
//i punti interrogativi non sempre sono chiari, così lo è di più<br />
$stpdo->execute(array(':name'=>'marcello',':id'=>17));<br />
$mypdo->commit();<br />
echo 'SELECT';<br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare('SELECT * FROM first_table');<br />
// eseguo la query<br />
$stpdo->execute();<br />
//stampo a video il contenuto dell'array che mi crea fetch<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$mypdo->commit();<br />
</code></p>
<p><strong>Metodo fetchAll</strong><br />
ritorna un array le righe del resultset<br />
<code><br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare('SELECT * FROM first_table');<br />
// eseguo la query<br />
$stpdo->execute();<br />
$row=$stpdo->fetchAll();<br />
//stampo a video il contenuto dell'array che mi crea fetch<br />
var_dump($row);<br />
$mypdo->commit();<br />
</code></p>
<p><strong>Metodo fetchAll</strong><br />
<code><br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare('SELECT * FROM first_table');<br />
// eseguo la query<br />
$stpdo->execute();<br />
$row=$stpdo->fetchAll(PDO::FETCH_OBJ);<br />
//così ho un array di oggetti<br />
//stampo a video il contenuto dell'array che mi crea fetch<br />
var_dump($row);<br />
$mypdo->commit();<br />
</code></p>
<h3>Metodi bind</h3>
<p><strong>bindParam</strong><br />
<code><br />
$id=10;<br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare("SELECT * FROM first_table WHERE id = ? ");<br />
$stpdo->bindParam(1,$id, PDO::PARAM_INT);<br />
$stpdo->execute();<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$mypdo->commit();<br />
</code><br />
Oppure:<br />
<code><br />
$id=10;<br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare("SELECT * FROM first_table WHERE id = :id ");<br />
$stpdo->bindParam(':id',$id, PDO::PARAM_INT);<br />
$stpdo->execute();<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$id=13;<br />
$stpdo->bindParam(':id',$id, PDO::PARAM_INT);<br />
$stpdo->execute();<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$mypdo->commit();<br />
</code><br />
Così ho preparato la query una volta sola, ed ho legato :id al valore della variabile $id.</p>
<p><strong>bindValue</strong><br />
<code><br />
$id=10;<br />
$mypdo->beginTransaction();<br />
$stpdo = $mypdo->prepare('SELECT * FROM first_table WHERE id < ? ');<br />
$stpdo->bindValue(1, $id, PDO::PARAM_INT);<br />
$stpdo->execute();<br />
while ($row=$stpdo->fetch())<br />
{<br />
     echo 'id: '.$row['id'].' - name: '.$row['name'].'&lt;br /&gt;';<br />
}<br />
$mypdo->commit();<br />
</code></p>
<p><strong>bindColumn</strong><br />
<code><br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare("SELECT * FROM first_table ");<br />
$stpdo->bindColumn(1,$id);<br />
$stpdo->bindColumn(2,$name);<br />
$stpdo->bindColumn(3,$surname);<br />
$stpdo->execute();<br />
while($row = $stpdo->fetch(PDO::FETCH_BOUND))<br />
    echo $id.' '.$name.' '.$surname.'&lt;br /&gt;'; // stampo i nomi<br />
$mypdo->commit();<br />
</code><br />
In pratica specifico prima come devono chiamarsi i dati letti da una query e di che tipo devono essere.<br />
a variabile $id non l&#8217;avevo mai creata, nonostante ciò non ho avuto nessun notice o warning perche&#8217; questa viene popolata e inizializzata ( se inesistente ) automaticamente all&#8217; interno della chiamata a bindColumn.<br />
Poi la variabile viene automaticamente riassegnata ad ogni ciclo del while ,<br />
permettendoci di evitare i soliti $row[N] per il fetch_row o $row['key'] per il fetch_assoc.</p>
<p><strong>bindColumn</strong><br />
<code><br />
$mypdo->beginTransaction();<br />
// preparo la query<br />
$stpdo = $mypdo->prepare("SELECT * FROM first_table ");<br />
$stpdo->bindColumn(1,$id, PDO::PARAM_INT);<br />
$stpdo->bindColumn(2,$name, PDO::PARAM_STR);<br />
$stpdo->bindColumn(3,$surname, PDO::PARAM_STR);<br />
$stpdo->execute();<br />
while($row = $stpdo->fetch(PDO::FETCH_BOUND))<br />
    echo $id.' '.$name.' '.$surname.'&lt;br /&gt;'; // stampo i nomi<br />
$mypdo->commit();<br />
</code></p>
<p>i parametri non modificano il risultato, ma &#8220;forse&#8221; ottimizzano le query</p>
<p>così abbiamo visto anche come funizona PDO::FETCH_BOUND</p>
<p>E se volessi usare Postgres invece di Mysql?<br />
Semplice creo il DB pgsql come quello mysql e basta che cambi queste rige con i diversi parametri di connessione:<br />
<code><br />
$string_dsn = 'pgsql:host=localhost;dbname=pdo'; // pgsql<br />
$string_username = 'user';<br />
$string_password = 'password';<br />
</code></p>
<p>ed il gioco è fatto, bello no?!</p>
<p>Lo studio l&#8217;ho fatto partendo da questi link:</p>
<p><a href="http://it2.php.net/pdo">http://it2.php.net/pdo</a><br />
<a href="http://forum.html.it/forum/showthread.php?s=&#038;postid=8143487">Pillola PDO</a></p>
<p>Gabba Gabba Hey<br />
Bonzo</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ilbonzo.org/2008/06/16/pdo-abstraction-layer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
