Lezione Precedente Elenco Lezioni Lezione Successiva

Laboratorio di Sistemi Informativi

Form HTML e Inserimento dati

Ora che abbiamo imparato come scrivere della pagine PHP che leggono da una base di dati, vediamo come realizzare altre pagine che effettuino operazioni di inserimento. In particolare, vogliamo implementare la funzionalità di inserimento di un nuovo oggetto nel database mancolista. Notare che, secondo la specifica, tale operazione dovrebbe essere consentita esclusivamente agli amministratori del sito, ma per il momento ignoriamo questa problematica.

Abbiamo visto nella lezione scorsa come è possibile passare parametri ad uno script PHP tramite la barra degli indirizzi. Fino ad ora, però, passavamo come parametro semplicemente l'id di un oggetto di cui volevamo avere i dettagli. Ora, invece, la procedura PHP che si occupa di inserire nuovi oggetti deve accettare vari parametri come il nome dell'oggetto da creare, descrizioni lunghe e corte, categorie, etc... La cosa non è però differente dal punto di vista concettuale. Possiamo allora scrivere la seguente pagina, che chiamiamo inserimento.php.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Inserimento Oggetti Mancolista di Paolo</title>
</head>
<body>
<?php
<require 'config.php';
$conn=new PDO(DSN,USERNAME,PASSWORD);
$conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$stmt=$conn->prepare("INSERT INTO oggetti (nome,descrizione,descrizione_lunga,categoria_id) VALUES (?,?,?,?)");
$stmt->execute(array($_GET['nome'],$_GET['descrizione'],$_GET['descrizione_lunga'],$_GET['categoria_id']));
echo "Inserimento avvenuto";
?>
</body>
</html>

In questo programma non troviamo niente di nuovo rispetto a quello che abbiamo già visto. Notare che non utilizziamo il metodo PDOStatement::fetch perché il comando INSERT non resituisce alcun risultato. Se l'inserimento avviene, visualizziamo il messaggio Inserimento avvenuto, mentre se per qualche motivo l'inserimento non può avvenire (ad esempio, non specifichiamo il parametro $_GET['nome'], che quindi assume il valore di default null) si genera una eccezione.

Per controllare se la pagina funziona, basta utilizzare una URL come quella che segue:

http://hostname/percorso/inserimento.phpnome=xyz&descrizione=aa&descrizione_lunga=prova&categoria_id=1

Le FORM in HTML

Al solito, non è pensabile che l'utente del sito specifichi tali parametri direttamente sulla URL. D'altronde, non è possibile fornire tutte queste informazioni semplicemente con l'uso di link opportuni come fatto per la pagina di dettagli. Serve un nuovo meccanismo di interazione con l'utente: le FORM. Consideriamo ad esempio la seguente pagina:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Prova PHP con parametri</title>
</head>
<body>
<form action="param.php" method="GET">
Inserire il testo per il parametro 1:
<input type="text" name="param1" size="10" maxlength="30">
<br>
Scegliere il valore per il parametro 2:
<select name="param2" size="1">
<option value="Valore 1">v1</option>
<option value="Valore 2">v2</option>
<option value="Valore 3">v3</option>
</select>
<br>
<input type="submit" value="Procedi!">
</form>
</body>
</html>

Questa definisce una form con tre campi di input. Un campo di tipo text, dove è possibile inserire del testo a piacere, un campo di tipo select  che consente di scegliere dei valori in un elenco prefissato, e un pulsante di tipo submit. Quando si preme il pulsante di submit, il browser passa alla pagina "param.php" (indicata come attributo del tag FORM) specificando (tramite l'URL) i valori inseriti nei vari campi di input. I nomi dei parametri sono quelli indicati nell'attributo name mentre il valore è quello inserito dall'utente del browser. Ad esempio, se si scrive "ciao" dentro il campo di testo, si seleziona "Valore 1" sul campo a scelta multipla e si clicca poi sul pulsante Procedi!, viene richiamato l'URL param.php?param1=ciao&param2=v1. Questo provoca il caricamento della pagina param.php vista la lezione precedente e la visualizzazione di

Il parametro param1 vale : ciao
Il parametro param2 vale : v1

Notare, a questo proposito, la struttura del tag option:

<option value="Valore 1">v1</option>


Il valore dell'attributo value è quello che viene visualizzato dal browser, mentre la stringa tra i tag <option> e </option> è quello che viene passato allo script param.php. Questo è il motivo per cui selezionando Valore 1 viene passata allo script successivo la stringa v1.

Inserimento dati con l'uso delle FORM

Vediamo di integrare la pagina inserimento.php con le FORM. L'idea è creare una pagina HTML con una form per l'immissione dei dati, che invochi la pagina inserimento.php con i dati opportuno. Il tutto è realizzato da questi due file:

Invece di avere due file distinti, uno per la form e l'altro per la procedura di inserimento, si può integrare il tutto in un unico script PHP. Quando viene chiamato senza parametri, visualizzerà la form di richiesta dati, altrimenti effettuerà la procedura di inserimento. Si ottiene il seguente file:

Nella nuova versione è da notare:
  1. l'uso di isset per stabilire se il parametro $_GET['nome'] è stato fornito oppure no. Se non è presente, vuol dire che deve essere presentata la FORM di immissione dati. Dopo che l'utente ha immesso i dati e cliccato sul pulsante Inserisci, la pagina inserimento-totale.php viene ricaricata, ma stavolta il parametro $_GET['nome'] è presente, e viene eseguita la procedura di inserimento.
  2. l'uso dell'attributo action vuoto nel tag FORM: il campo action vuoto indica la pagina web corrente. Equivale a scrivere inserimento-totale.php ma è più comodo, perché se decidiamo di cambiare nome al file non è necessario effettuare nessuna modifica alla form.

Questa soluzione può essere vantaggiosa per tenere in un unico file tutto il codice PHP e HTML richiesto per una applicazione ben specifica. D'altronde la soluzione con due file distinti è più modulare... occorre giudicare dai casi.

Inserimento dati con selezione della categoria

La form che abbiamo usato qui sopra non è proprio adatta ad un utente comune: quest'ultimo, infatti, non è detto che conosca quali sono le categorie al momento presenti nel database, e sicuramente non ne conosce i codici numerici, che è invece il dato che la form si aspetta nel campo ID categoria. Bisogna modificare la form in modo che compaia un elenco di categorie valide tra cui scegliere. Questa è una prima soluzione:

Questa soluzione ha il difetto che ogni volta che aggiungiamo o eliminiamo una categoria dalla base di dati, occorre modificare la pagina web. Quello che bisogna fare è generare un FORM automaticamente sulla base dei dati presenti nella tabella categoria. Consideriamo la seguente modifica del file di prima:

Questo nuovo script interroga il database MySQL per determinare quali sono le categorie disponibili, e costruisce dei campi di input di tipo SELECT appropriati. Modifiche alla base di dati si riflettono immediatamente sulle pagine web generate: non occorre quindi nessuna manutenzione speciale per adattare il sito web alla nuova situazione.

Metodi GET e POST

Abbiamo visto  come passare dei parametri ad uno script in PHP inserendoli nella URL. All'interno di una form, si può specificare che si intende utilizzare questo metodo per il passaggio dei parametri inserendo, nel tag <FORM>, l'attributo method="GET". Esssendo GET il valore di default dell'attributo method, in realtà questa specifica è facoltativa. Tuttavia, esiste un altro metodo per il passaggio dei parametri ad uno script, il metodo POST.

Per utilizzare il metodo POST basta effetturare un paio di cambiamenti rispetto a quanto fatto finora:
  1. aggiungere l'attributo METHOD=POST nel tag FORM;
  2. sostituire tutte le occorrenze della variabile $_GET con la variabile $_POST nello script che viene richiamato.
Lo script inserimento2-totale-post.php è la versione di form-totale.php modificato per utilizzare il metodo POST. Vediamo adesso in dettaglio alcune delle differenze tra i metodi GET e POST.
Differenza n. 1: visibilità dei parametri
Il metodo POST, a differenza del GET, non utilizza la URL per il passaggio dei parametri. Questi vengono comunque passati al momento della richiesta della pagina, ma con un meccanismo interno che non è visibile all'utente.  Per questo, il metodo POST è più adatto se bisogna inviare come parametri dei valori sensibili: numeri di carte di credito, password, etc.. Usando il metodo GET, una persona che passa per caso davanti al computer potrebbe sbirciare il contenuto della URL e scoprire il numero della vostra carta di credito!

A dire il vero questo accorgimento è del tutto insufficiente per dati così importanti come il numero di carta di credito. In questo caso è assolutamente necessario che tutta la comunicaziona tra browser e server web avvenga in maniera criptata, usando il protocollo https invece di http. Questo è però al di là degli obiettivi di questo corso.
Differenza n.2: bookmarks
Se si salva nei segnalibri (detti anche preferiti, o bookmarks) l'indirizzo di una pagina web, verranno salvati anche i valori di eventuali parametri passati col metodo GET alla pagina. Parametri passati col metodo POST non vengono salvati. Per questo, quando la pagina che vogliamo visualizzare contiene dei dati che può essere interessante rileggere in un momento successivo (ad esempio la pagina di dettaglio di un oggetto), il metodo GET è da preferire. 

È per questo che tutti gli script visti nella lezione precedente utilizzano il metodo GET. Se si salva nei bookmark l'indirizzo http://server/percorso/dettagli.php?id=1 sarà possibile accedere direttamente ai dati del fumetto con id 1 senza ripassare per l'indice di tutti gli oggetti.
Differenza n.3: ricaricamento della pagina
Se si preme il tasto reload su una pagina a cui sono stati passati dei parametri con il metodo POST, il browser non ricarica automaticamente la pagina. Avverte prima l'utente che ci sono stati dei parametri passati con il POST e chiede se veramente si vuole ricaricare la pagina (in tal caso i parametri vengono passati di nuovo).

Il motivo di questo comportamento ferraginoso è che il metodo POST è di solito utilizzato per passare dei parametri agli script che modificano una base di dati, mentre il GET viene usato per gli script che interrogano una base di dati. Fare due interrogazioni ad un base di dati non è un problema, anche se lo si fa per sbaglio, ma fare due modifiche alla base di dati per sbaglio, quando invece se ne voleva fare solo una, è tutta un'altra cosa. Per questo il browser chiede conferma che effettivamente si voglia ricaricare la pagina (col rischio di effettuare qualche modifica non prevista).

Metodi GET e POST a livello di protocollo HTTP (materiale aggiuntivo)

Se scendiamo fino a livello del protocollo HTTP, due sono le differenze fondamentali tra le richieste GET e quelle POST:

  1. il comando HTTP utilizzato: GET nel caso di richiesta GET, POST nel caso di richiesta POST;
  2. la modalità di passaggio dei parametri: nella URL per il metodo GET, nel corpo della richiesta HTTP per il metodo POST.

Ad esempio, consideriamo la form vista all'inizio della lezione, adoperata per passare parametri opportuni a param.php. Nel caso di utilizzo del metodo GET, una tipica richiesta HTTP sarà la seguente:

GET /~amato/param.php?param1=pippo&param2=Valore+1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.14) Gecko/20080418 Ubuntu/7.10 (gutsy) Firefox/2.0.0.14
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.7,it;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/~amato/param.html

Se però modifichiamo il sorgente della form sostituendo POST a GET nell'attributo METHOD ed effettuiamo un'altra richiesta, questa si presenterà così:

POST /~amato/param.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.14) Gecko/20080418 Ubuntu/7.10 (gutsy) Firefox/2.0.0.14
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.7,it;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/~amato/param.html
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 28

param1=pippo&param2=Valore+1

Sono state evidenziate in rosso le differenze più significative. Notare che l'intestazione termina con le righe Content-Type e Content-Length che indicano la presenza di un corpo della richiesta, e che la stringa param1=pippo&param2=Valore+1 viene passata appunto nel corpo e non nella URL.

Lezione Precedente Elenco Lezioni Lezione Successiva

Valid HTML 4.01 Transitional Valid CSS!