72 PDO 2
Rielaboriamo la pagina precedente creando registra_dati_questionario_PDO.php. Effettuiamo la conessione:
try
{
$conn = new PDO("mysql:host=localhost;dbname={$accessData['dbname']}",
$accessData['username'],$accessData['password']);
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Connessione al server fallita. Impossibile procedere. Contattare ...";
die();
}
Mentre per la connessione possiamo sfruttare il try e il catch, per gli altri comandi dobbiamo attivare il supporto alle eccezioni. Per far questo sobbiamo attivare il metodo setAttribute sul nostro oggetto PDO ($conn):
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
L’attributo che ci interessa è ERRMODE cioè la modalità di gestione degli errori, una collezione di costanti predefinite all’interno della classe PDO. Il secondo attributo, ERRMODE_EXCEPTION, è la gestione delle eccezioni degli errori. Continuiamo il codice con la query di inserimento dati nella tabella questionario:
$data_oggi = date("Y-m-d");
$comandoSQL = "insert into questionari values (null, " .
$conn->quote($_POST['descrizione']) . ", " .
"'" . $data_oggi . "', " .
"'" . $_SESSION['iduser'] . "')";
L’unica diversità dalla precedente versione è la protezione dei SQL injection con il metodo quote. Siamo pronti per lanciare il comando e lo faremo con un costrutto try / catch:
try
{
$conn->query($comandoSQL);
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Inserimento fallito ...";
die();
}
a questo punto se sbagliassimo, per esempio, il nome di una tabella, l’exception degli errori ci avviserebbe chiaramente sull’errore commesso.
Andiamo ora a recuperare l’ultimo id inserito col metodo PDO:
$idQuestionario = $conn->lastInsertId();
lastInsertId recuera l’ltimo id col metodo PDO. Ora possiamo usare i prepared statments con la classe PDO
$conn->prepare("insert into items values (null, ?, ?)");
La sintassi del binding è simile :
$comando_prepared->bindParam(1, $fkQuestionario, PDO::PARAM_INT); $comando_prepared->bindParam(2, $fkDomanda, PDO::PARAM_INT);
Il metodo di PDO per i prepared statments è bindParam, gli argomenti sono il primo parametro, la variabile collegata ($fkQuestionario), e a differenza del procedurale dove inserivo i per intero, qui bisogna specificare PDO::PARAM_INT , per le stringhe bisogna specificare anche la lunghezza.
Ora recuperiamo le domande scelte sui checkbox della form e generiamo un ciclo for con il codice questionario sempre uguale e il codice della domanda che varia
$domande = $_POST['domande_scelte'];
for($i=0; $i<count($domande); $i++)
{
$fkQuestionario=$idQuestionario;
$fkDomanda=$domande[$i];
Eseguimo la query sempre con la gestione delle eccezioni e il comando execute:
try
{
$comando_prepared->execute();
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Inserimento fallito ...";try
{
//allora eliminiamo il questionario
$conn->query("delete from questionari where idquestionario=$idQuestionario");
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Impossibile eliminare ...";
}
die();
}
Dovesse fallire l’inserimento nella tabella items, bisogna provvedere anche all’eliminazione dei dati inseriti nella tabella questionario
$conn->query("delete from questionari where idquestionario=$idQuestionario");
Nel caso fallisse la cancellazione del questionario, riceverò un doppio messaggio di errore (una doppia eccezione), una per il fallimento items e una per il fallimento cancellazione questionario. Da notare l’annidamento doppio delle eccezioni try / catch.
Esiste un secondo metodo per usare i prepared statments coi PDO che è leggermente più facile, perché utilizza il nome del nostro segnaposto::
$comando_prepared =
$conn->prepare("insert into items values (null, :fkQuestionario, :fkDomanda)");
e la analoga variante del binding:
$comando_prepared->bindParam(':fkQuestionario', $fkQuestionario , PDO::PARAM_INT);
$comando_prepared->bindParam(':fkDomanda', $fkDomanda, PDO::PARAM_INT);
Come si può notare si usano i nomi dei campi da popolare.
Di seguito il codice completo di tutta la pagina:
<?php
include($_SERVER['DOCUMENT_ROOT']."/fagtest/my_include/setup_con_DB.php");if ( !isset($_SESSION['iduser']) )
{
header("Location: login.php?errore=autenticazione_richiesta"); //user non autenticato
exit;
}
try
{
//CONNESSIONE
$conn = new PDO("mysql:host=localhost;dbname={$accessData['dbname']}",
$accessData['username'],$accessData['password']);
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Connessione al server fallita. Impossibile procedere. Contattare ...";
die();
}
//ATTIVAZIONE ECCEZIONI PER METODO QUERY
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//prima inseriamo la riga del questionario nella tabella questionari
$data_oggi = date("Y-m-d");
$comandoSQL = "insert into questionari values (null, " .
$conn->quote($_POST['descrizione']) . ", " .
"'" . $data_oggi . "', " .
"'" . $_SESSION['iduser'] . "')";
try
{
$conn->query($comandoSQL);
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Inserimento fallito ...";
die();
}
$idQuestionario = $conn->lastInsertId();
//PREPARED STATEMENTS
//$comando_prepared =
//$conn->prepare("insert into items values (null, ?, ?)");
$comando_prepared =
$conn->prepare("insert into items values (null, :fkQuestionario, :fkDomanda)");
//binding segnaposto ? con rispettive variabili
//$comando_prepared->bindParam(1, $fkQuestionario, PDO::PARAM_INT);
//$comando_prepared->bindParam(2, $fkDomanda, PDO::PARAM_INT);
$comando_prepared->bindParam(':fkQuestionario', $fkQuestionario , PDO::PARAM_INT);
$comando_prepared->bindParam(':fkDomanda', $fkDomanda, PDO::PARAM_INT);//recuperiamo le domande scelte sulla form
$domande = $_POST['domande_scelte'];
for($i=0; $i<count($domande); $i++)
{
$fkQuestionario=$idQuestionario;
$fkDomanda=$domande[$i];
try
{
$comando_prepared->execute();
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Inserimento fallito ...";
try
{
//allora eliminiamo il questionario
$conn->query("delete from questionari where idquestionario=$idQuestionario");
}
catch (PDOException $e)
{
echo $e->getMessage() . "<br/>";
echo "Impossibile eliminare ...";
}
die();
}
}
//CHIUDIAMO LA CONNESSIONE E LIBERIAMO LE RISORSE OCCUPATE ...
$conn=null;
/* if ($esito)
$idQuestionario = mysqli_insert_id( $conn );
else
{
mysqli_close($conn);
header("Location: login.php?errore=inserimento_fallito"); //inserimento fallito
}//per gli N insert into per la tabella degli items conviene usare
//i prepared statement
$comando_prepared =
mysqli_prepare($conn, "insert into items values (null, ?, ?)");
//i=intero, d=double, s=stringa
mysqli_stmt_bind_param($comando_prepared, "ii", $fkQuestionario, $fkDomanda);
$domande = $_POST['domande_scelte'];
for($i=0; $i<count($domande); $i++)
{
$fkQuestionario=$idQuestionario;
$fkDomanda=$domande[$i];
mysqli_stmt_execute($comando_prepared);
}
mysqli_stmt_close($comando_prepared);
mysqli_close($conn);
*/
?>