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);
*/
?>