PHP, Web and Mobile development

Usiamo il PHP 4

Utilizziamo praticamente il PHP risolvendo i problemi più comuni.

Nel precedente articolo abbiamo affrontato gli elementi fondamentali del linguaggio PHP: variabili, tipi di dato, operatori e le strutture di controllo. In questo articolo, invece, illustreremo aspetti pratici dell’uso di questo linguaggio, in particolare il passaggio delle informazioni attraverso diverse pagine dinamiche, la spedizione di messaggi di posta elettronica, l’upload di files e la gestione dei cookie.

Variabili esterne al PHP

Il successo del PHP è dovuto ad una delle sue più gradite funzionalità. Ovvero quella di trasformare variabili esterne al PHP in variabili globali all’interno del codice. In particolare: tutti i parametri di una URL, tutti i campi di un form, tutti i cookie trasmessi dal browser. Per esempio se richiamiamo una pagina PHP tramite la seguente URL:

http://www.infomedia.it/test.php?citta=Milano&colore=rosso

noteremo che il PHP crea automaticamente le variabili globali $citta e $colore contenenti i valori specificati sulla URL. Stessa cosa nel caso di un form, se ad esempio inviamo il seguente form:

	<form action="http://www.infomedia.it/test.php">
	<input type=hidden name="citta" value="Milano">
	<input type=hidden name="colore" value="rosso">
	<form>

una volta ricevuto dalla pagina PHP viene creata una variabile globale per ogni campo del form avente come nome il nome del campo (il parametro name) e per valore il valore delo campo stesso (il parametro value). Questo permette al PHP di operare con estrema facilità e velocità sui form senza ricorrere a librerie aggiuntive come e il caso dei cgi sopratutto quelli scritti in Perl.

Inviamo una e-mail

Un esempio molto semplice dell’utilizzo di questa funzionalità del PHP e la costruzione di un form per l’invio di una e-mail. L’esempio sarà costruito su due pagine. La prima pagina dinamica (Listato 1) sarà chiamata esempio1a.php, ed avrà lo scopo di presentare un form all’utente con i differenti campi da riempire. Se consultate il listato noterete che questi sono: nome ed e-mail sia del mittente che del destinatario, il titolo ed il corpo del messaggio da inviare via e-mail. Per facilitare l’inserimento dei dati, i campi del form sono stati organizzati in una tabella mentre l’attributo action del tag form punta alla pagina successiva cui i dati saranno trasmessi.

Infatti, la seconda pagina dinamica dell’esempio (Listato 2) sarà chiamata esempio1b.php, guardando il listato noteremo che è diviso in due parti: la prima si occupa di controllare che tutti i parametri siano corretti; la seconda, invece, costruisce ed invia il messaggio di posta elettronica.

In particolare tutti i campi sono obbligatori e quindi non possono essere vuoti. Nel caso di errori viene visualizzato un messaggio che invita a completare correttamente i campi e viene visualizzato un bottone con la dicitura “Riprova“. Questo bottone è associato ad un form che contiene una serie di campi di tipo hidden (nascosti) che forniscono un valido esempio di come inviare dati tra due pagine senza visualizzarli all’utente. La spedizione dell’e-mail viene effettuata tramite la funzione mail() interna al PHP che ha la seguente sintassi:

 mail( $to, $titolo, $testo, $headers );

dove $to è l’e-mail del destinatario, $titolo il titolo dell’e-mail (o subject), $testo è il corpo del messaggio e $headers sono degli header aggiuntivi che si vogliono aggiungere alla e-mail.

Risolviamo alcuni problemi

Nel nostro esempio abbiamo specificato una serie di header (si veda RFC-822[3])per ovviare ad alcuni problemi. Il primo problema è quello del mittente. La funzione mail() del PHP manda i messaggi in uscita tramite l’indirizzo del web-server che molto spesso è nobody@miodominio.com dove nobody è l’utente sotto le cui permissions gira il web-server mentre miodominio.com è il nome del dominio servito da quel web-server.

Per risolvere questo problema e cambiare il mittente occorre aggiungere degli headers relativi alle voci “From:” e “Reply-To:” più “Return-Path:” per ricevere eventuali messaggi di errore come per esempio l’impossibilità di consegnare al destinatario il messaggio di posta. Inoltre dobbiamo risolvere alcuni problemi di sicurezza aggiungendo una serie di headers customizzati, inizianti con “X-”, che servano ad identificare la persona che ha utilizzato il form. Per questo motivo abbiamo aggiunto gli header X-Sender-IP e X-Sender-Port altrimenti chiunque potrebbe utilizzare il nostro form per mandare spam o e-mail anonime.

Gestione degli upload

Il PHP consente anche la gestione degli upload (si veda RFC-1867[2]) sia di file testuali che di binari, come ad esempio un’immagine. Per far questo e necessario creare un form particolare (Listato 3) come qui illustrato:

<form enctype="multipart/form-data" action="esempio2b.php" method=POST>
	<input type=hidden name="MAX_FILE_SIZE" value="100000">
	<input type=file   name="miofile"> 
	<input type=submit value="Invia file">
	</form>

Il campo nascosto MAX_FILE_SIZE deve precedere il campo di tipo “file“. Il suo valore indica la dimensione massima in bytes del file da inviare. Il campo “miofile” può assumere qualsiasi nome, quello utilizzato è solo per esempio. Accanto a questo campo appare un bottone con la dicitura “Browse“. L’utente, premendo questo bottone, può sfogliare il filesystem della propria macchina per individuare il file da inviare. Una volta selezionato il file, il percorso dello stesso, apparirà automaticamente nella casella di testo relativa al campo “miofile“.

Una volta inviato il form, nella seconda pagina (Listato 4) chiamata esempio2b.php, il PHP crea automaticamente le seguenti variabili, aggiungendo un suffisso al nome del campo di tipo “file”:

  • $miofile, contiene il percorso completo dove è stato temporaneamente memorizzato il file inviato al server, solitamente risiede all’interno della directory “/tmp“;
  • $miofile_name, il nome originale del file inviato, ad esempio gatto.gif;
  • $miofile_size, la dimensione in bytes del file inviato;
  • $miofile_type, il mime-type del file inviato, per esempio “image/gif” nel caso di una immagine in formato GIF.

A questo punto è compito del programmatore controllare che la dimensione del file rispetti opportuni parametri e che il tipo di file inviato corrisponda a quello effettivamente desiderato. In particolare il file temporaneo (indicato da $miofile) deve essere copiato o spostato dalla sua posizione attuale perché, al termine della pagina dinamica, il PHP provvederà a rimuoverlo. Nella pagina esempio2b.php (Listato 4) abbiamo quindi utilizzato la funzione del PHP copy() per copiare il file dalla directory temporanea nella directory dove risiede la nostra pagina PHP. E’ opportuno notare che il web-server deve avere i permessi di scrittura sulla directory dove vengono copiati i files altrimenti verrà riportato un messaggio d’errore riguardante le permissions.

I Cookies

Il PHP come visto in precedenza, supporta i cookie[1] in maniera trasparente. Per chi non conosce i cookie potremmo definirli molto semplicemente come un meccanismo per memorizzare piccole quantità di dati attraverso il browser dell’utente. I cookie funzionano nel seguente modo: quando il browser accede una pagina dinamica questa può inviargli oltre il contenuto della pagina stessa anche delle informazioni addizionali, tra queste ci potrebbero essere anche dei cookie che vengono memorizzati dal browser in un file apposito (per Netscape cercate il file cookie.txt). Ogni qualvolta il browser riaccede quel dominio o quella specifica pagina, oltre alla richiesta della pagina da caricare invia anche tutti i cookie che ha ottenuto da quella pagina. Questo meccanismo è usato da alcuni siti, come ad esempio Amazon.com, per tracciare l’attività degli utenti sul suo sito e customizzare le pagine con i prodotti maggiormente richiesti. Grazie ai cookie, quindi, un sito può tracciare l’attività, le preferenze e ogni quando ritorna un determinato utente.

In PHP si può impostare un cookie tramite la funzione SetCookie() facendo attenzione che, essendo i cookie parte degli header del protocollo HTTP, la funzione SetCookie() deve essere utilizzata in testa alla pagina dinamica, prima che qualsiasi contenuto della pagina HTML venga inviato. La funzione SetCookie ha la seguente sintassi:

 int setcookie( string nome, string valore, int data_expire, string path, string dominio, int flag_SSL);

Ed i differenti parametri hanno il seguente significato:

  • nome, indica il nome del cookie da creare;
  • valore, indica il valore da dare al cookie;
  • data_expire, indica la data di expire del cookie, da quel momento in poi il cookie non sarà più considerato valido dal browser e verrà quindi cancellato. Per definire questa data si può aggiungere un numero finito di secondi al risultato della funzione time() oppure utilizzare la funzione mktime();
  • path, è un parametro opzionale che indica il percorso della pagina cui deve essere restituito il cookie, per qualche oscuro motivo, probabilmente un baco della versione 3 del PHP, il mio consiglio é quello di utilizzare sempre la “/” per questo parametro, anche se opzionale, quando si crea un cookie;
  • dominio, è un parametro opzionale che indica il dominio per cui è valido il cookie;
  • flag_SSL, è un parametro opzionale che indica se il cookie deve essere trasmesso solo in caso di una connessione sicura, ovvero HTTPS.

Nel Listato 5 che deve essere rinominato esempio3.php, abbiamo un semplice esempio di utilizzo dei cookie. Con il primo form impostiamo un cookie chiamato “miocookie”, mentre con il secondo form lo rimuoviamo. In realtà i due form servono solo a passare i parametri che verranno poi utilizzati successivamente dalla stessa pagina PHP per impostare o rimuovere il cookie. Potete creare cookie con altri nomi, è importante notare che il numero massimo di cookie per ogni URL è di 20, dopo il ventesimo cookie quelli precedenti verranno rimossi per far spazio ai nuovi.

Conclusioni

Con questo articolo abbiamo affrontato alcuni interessanti problemi pratici in cui il PHP mette a disposizione dello programmatore una serie di potenti funzioni per risolverli in maniera molto semplice. Nel prossimo articolo tratteremo l’accesso alle basi di dati ed in particolare utilizzo di MySQL. Vedremo quindi come connettersi ad un database ed operare semplici istruzioni SQL.

Riferimenti

[1] Specifiche della Netscape sui Cookie – http://www.netscape.com/newsref/std/cookie_spec.html

[2] RFC 1867 – http://community.roxen.com/developers/idocs/rfc/rfc1867.html

[3] RFC-822 – http://community.roxen.com/developers/idocs/rfc/rfc822.html

Listati

Listato 1

<html>
<head><title>Listato 1 - esempio1a.php</title></head>
<body>

<p>
Con questo modulo puoi spedire un messaggio di posta elettronica. 
Tutti i campi sono obbligatori, ricordati quindi di non 
lasciarli vuoti.
</p>

<form action="esempio1b.php" method=POST>
<table align=center>

<!-- nome mittente -->
<tr>
<td align=right>Nome mittente:</td>
<td><input type=text name="nome1" value="<? echo $nome1 ?>"></td>
</tr>

<!-- e-mail mittente -->
<tr>
<td align=right>E-mail mittente:</td>
<td><input type=text name="mail1" value="<? echo $mail1 ?>"></td>
</tr>

<!-- nome destinatario -->
<tr>
<td align=right>Nome destinatario:</td>
<td><input type=text name="nome2" value="<? echo $nome2 ?>"></td>
</tr>

<!-- e-mail destinatario -->
<tr>
<td align=right>E-mail destinatario:</td>
<td><input type=text name="mail2" value="<? echo $mail2 ?>"></td>
</tr>

<!-- titolo -->
<tr>
<td align=right>Titolo:</td>
<td><input type=text name="titolo" value="<? echo $titolo ?>"></td>
</tr>

<!-- messaggio -->
<tr>
<td align=right>Messaggio:</td>
<td><textarea name="testo" rows=10 cols=78 wrap=physical>
<? echo $testo ?>
</textarea></td>
</tr>


<!-- bottone di invio -->
<tr>
<td>&nbsp;</td>
<td><input type=submit value="Invia"></td>
</tr>

</table>
</form>


</body>
</html>

Listato 2

<html>
<head><title>Listato 2 - esempio1b.php</title></head>
<body>

<?
  /* Controlliamo i parametri */

  $errori=0;		// Numero di errori riscontrati

  /* Controlliamo che i campi non siano vuoti */
  if (trim($nome1)=='') {
    echo "<li>Non hai specificato il nome del destinatario</li><br>\n";
    $errori++;
  }
  if (trim($nome2)=='') {
    echo "<li>Non hai specificato il nome del mittente</li><br>\n";
    $errori++;
  }
  if (trim($mail1)=='') {
    echo "<li>Non hai specificato l'e-mail del mittente</li><br>\n";
    $errori++;
  }
  if (trim($mail2)=='') {
    echo "<li>Non hai specificato l'e-mail del destinatario</li><br>\n";
    $errori++;
  }
  if (trim($titolo)=='') {
    echo "<li>Non hai specificato il messaggio</li><br>\n";
    $errori++;
  }
  if (trim($testo)=='') {
    echo "<li>Non hai specificato il messaggio</li><br>\n";
    $errori++;
  }

  /* Controllo numero di errori */
  if ($errori>0) {
?>
<p>Impossibile inviare il messaggio di posta elettronica. 
Correggi gli errori riportati e riprova.</p>
<form action="esempio1a.php" method=POST>
<input type=hidden name="nome1"  value="<? echo $nome1 ?>">
<input type=hidden name="mail1"  value="<? echo $mail1 ?>">
<input type=hidden name="nome2"  value="<? echo $nome2 ?>">
<input type=hidden name="mail2"  value="<? echo $mail2 ?>">
<input type=hidden name="titolo" value="<? echo $titolo ?>">
<input type=hidden name="testo"  value="<? echo $testo ?>">
<input type=submit value="Riprova">
</form>
<?
    // fine gestione errori
    exit;
  }  

  /* Spedizione del messaggio di posta */
  $mail_to   = trim($nome2) .' <'. trim($mail2) .'>';
  $headers   = 'From: '. trim($nome1) .' <'. trim($mail1) .'>'."\n".
               'Reply-To: '. trim($mail1) ."\n".
               'Return-Path: '. trim($mail1) ."\n".
	       'X-Mailer: PHP/'. phpversion() ."\n".
               'X-Sender-IP: '. getenv("REMOTE_ADDR") ."\n".
               'X-Sender-Port: '. getenv("REMOTE_PORT") ."\n\n";

  // invio e-mail
  mail( $mail_to, $titolo, $testo, $headers );
  
?>  
<b>Complimenti! La tua mail per <? echo $nome2 ?> &egrave; stata
inviata correttamente</b>

</body>
</html>

Listato 3

<html>
<head><title>Listato 3 - esempio2a.php</title></head>
<body>

<p>
Con questo modulo puoi inviare un'immagine tramite il browser
e caricarla sulla tua homepage. Qualsiasi file puo' essere
inviato fintanto che contenga un'immagine.
</p>

<form action="esempio2b.php" method=POST enctype="multipart/form-data" >
<input type=hidden name="MAX_FILE_SIZE" value="10000">
File da inviare: <input type=file name="miofile" size=40><br>
<input type=submit value="Invia File"></td>
</form>

</body>
</html>

Listato 4

<html>
<head><title>Listato 4 - esempio2b.php</title></head>
<body>

<h1>variabili relative al form</h1>
<table>
<tr><td align=right>$miofile:</td><td><? echo $miofile ?></td></tr>
<tr><td align=right>$miofile_name:</td><td><? echo $miofile_name ?></td></tr>
<tr><td align=right>$miofile_size:</td><td><? echo $miofile_size ?></td></tr>
<tr><td align=right>$miofile_type:</td><td><? echo $miofile_type ?></td></tr>
</table>
<hr noshade size=1>
<h1>Risultato</h1>
<?

  /* Controlla se e' stato inviato qualcosa */
  if ($miofile_size == 0 ) {
    echo "<b>Il file inviato &egrave; vuoto!</b>";
    exit;
  }

  /* Controlla le dimensioni del file inviato */
  if ($miofile_size > 10000 ) {
    echo "<b>Il file inviato &egrave; troppo grande!</b>";
    exit;
  }
  
  /* Controlla il tipo di file inviato */
  if ( substr($miofile_type,0,6) != 'image/' ) {
    echo "<b>Il file inviato non &egrave; una immagine !</b>";
    exit;
  }

  /* Copia il file sulla homepage */
  $immagine = './'. strtolower($miofile_name);
  if (! copy($miofile,$immagine) ) {
    echo "<b>Si &egrave; verificato un errore mentre copiavo il file".
         "sull'homepage controllare i diriti di scrittura della".
         "directory dove risiede il codice PHP</b>";
    exit;
  }
  
?>
<a href="<? echo $immagine ?>"><img alt="<? echo $miofile_name ?>" border=1 src="<? echo $immagine ?>"></a>

</body>
</html>

Listato 5

<?
  /* Controlla la scelta dell'utente */
  if ($azione==impostacookie) {
    // imposta il cookie
    SetCookie( 'miocookie', $valore, time()+3600, '/' );
    // ricarica la pagina affinche il browser ritrasmetta il cookie
    echo '<a href="esempio3.php">E\' necessario ricaricare la pagina, clicca qui.</a>';
    exit;
  } else
  if ($azione==rimuovicookie) {
    // cancella il cookie impostanto l'expire_date al secondo precedente
    SetCookie( 'miocookie', '', time()-1, '/' );
    // ricarica la pagina affinche il browser rimuova il cookie
    echo '<a href="esempio3.php">E\' necessario ricaricare la pagina, clicca qui.</a>';
    exit;    
  }
?>
<html>
<head><title>Listato 5 - esempio3.php</title></head>
<body>
<?
  /* Controlla se il cookie e' stato trasmetto dal browser */
  if ( ! isset($miocookie) ) {
    echo "<h1>Nessun cookie impostato</h1>";
  } else {
    echo "<h1>miocookie=$miocookie</h1>";
  }
?>

<form action="esempio3.php" method=POST>
<input type=hidden name="azione" value="impostacookie">
Valore: <input type=text name="valore" value="">
<input type=submit value="Imposta il cookie">
</form>

<form action="esempio3.php" method=POST>
<input type=hidden name="azione" value="rimuovicookie">
<input type=submit value="Rimuovi il cookie">
</form>

</body>
</html>