[successivo] [precedente] [inizio] [fine] [indice generale] [violazione GPL] [translators] [docinfo] [indice analitico] [volume] [parte]


Capitolo 217.   L'utilizzo delle funzioni in PHP

Una funzione può essere intesa come un "sotto-programma" a cui si possono fornire dei valori per ottenere una risposta da essi dipendente o meno.

Il PHP mette a disposizione degli sviluppatori una vasta gamma di funzioni predefinite, tuttavia in alcune situazioni è necessario eseguire operazioni particolari, in questi casi è possibile definire delle funzioni personali che si comportano secondo le proprie necessità.

Si prenda d'esempio lo script del paragrafo 215.3.5 in cui si visualizzava la data formattata in un modo particolare, è improponibile dover scrivere 38 righe di codice ogni volta che si desidera visualizzare la data all'interno di una pagina HTML in questo caso la soluzione migliore è realizzare una funzione dedicata che restituisce la data mediante una semplice "chiamata". Per evitare errori e ripetitive modifiche è consigliabile realizzare uno o più file in cui raccogliere le funzioni personali più utilizzate, una sorta di libreria, da premettere in ogni pagina tramite il costrutto include().

217.1   Le funzioni predefinite

Come detto in principio non è volontà dell'autore riportare l'elenco delle funzioni PHP, esse sono catalogate ed abbondantemente illustrate nel manuale ufficiale reperibile al sito internet: <http://www.php.net>.

Di seguito si vuole illustrare la struttura del manuale e il modo in cui esso va consultato per cercare, scegliere ed infine utilizzare le innumerevoli funzioni predefinite del linguaggio. Come sempre il modo migliore è l'utilizzo di un semplice esempio. Si supponga di voler realizzare uno programma che visualizzi una porzione di una stringa. Bisogna come prima cosa individuare le funzioni che permettono di manipolare le stringhe.

Nella sezione "IV. Guida Funzioni" sono catalogate le funzioni messe a disposizione del programmatore, esse sono raggruppate per argomento. La sottosezione "LXXXIII. String functions" contiene le funzioni dedicate alla gestione delle stringhe. Come prima cosa si trova una descrizione della sezione e poi un lungo elenco, in ordine alfabetico, di funzioni con accanto una breve ma molto intuitiva descrizione. La funzione substr() potrebbe risolvere il problema sollevato nell'esempio.

Nel primo blocco della pagina descrittiva si trova il nome della funzione subito seguito dalle versioni dell'interprete PHP che la gestiscono e da una breve descrizione. Nel caso particolare:

   substr
   (PHP 3, PHP 4 >= 4.0.0)

   substr -- Return part of a string

A seguire la descrizione approfondita che inizia con una delle parti più importanti della documentazione, infatti, in una sola riga viene spiegato l'intero funzionamento del comando. Nell'esempio proposto:

   string substr (string string, int start [, int length])

Come detto questa è forse la parte più importante, la prima parola descrive il tipo di dato restituito dalla funzione, nel caso particolare string, dunque la funzione restituisce una stringa. Dopo il nome della funzione tra parentesi i valori che la funzione può accettare ed il relativo tipo di dato, va sottolineato che tra parentesi quadre vengono elencati i parametri non obbligatori e il relativo tipo di dato.

Nel particolare la funzione accetta un primo dato di tipo stringa, separato da virgola il numero del carattere di partenza di tipo intero (si parte sempre da 0 e non da 1) ed infine come dato opzionale la lunghezza, di tipo intero, della porzione di stringa da estrarre.

A questo schema seguono una descrizione approfondita ed una serie di esempi di funzionamento. Gli esempi se presenti sono molto utili ed autoesplicativi, inoltre trattano varie eccezioni ed eventuali casi particolari.

In fine ma non meno importante la sezione contenente le funzioni correlate o in qualche modo relazionate con quella in oggetto. Il manuale spesso suggerisce di consultare anche altre funzioni, in questo caso:

   See also strrchr() and ereg(). 

Spesso non esiste un unico modo per raggiungere la soluzione del problema e spesso questa ultima sezione fornisce degli spunti molto interessanti che possono portare ad una soluzione più semplice e brillante, il consiglio è di non sottovalutarla.

A questo punto è doveroso trattare almeno un esempio di utilizzo della funzione scelta come campione.

0   <?
1       // La stringa iniziale va in $var
2          $var = "Questa è la stringa di partenza";
3       //         0123456789012345678901234567890
4       //                  1234567890
5 
6       // Le due righe superiori semplificano il conteggio dei caratteri.
7 
8       // Questo esempio prende la parte: "la stringa"
9           $sub = substr($var, 9, 10);
10          echo $sub;
11
12      // Per selezionare gli ultimi 2 caratteri basta usare:
13          $sub = substr($var, -2);
14          echo "<br><br> ".$sub;
15
16      // Per selezionare i primi 2 caratteri basta usare:
17          $sub = substr($var, 0, 2);
18          echo "<br><br> ".$sub;
19              
20      // Se non specifico la lunghezza della porzione continua fino alla fine
21          $sub = substr($var, 5);
22          echo "<br><br> ".$sub;
23  ?>

Il risultato di questo semplice script è simile a:

la stringa

za

Qu

a è la stringa di partenza

Anche questo esempio è raggiungibile all'indirizzo: <http://www.urcanet.it/brdp/php_manual/esempi/cap_4/substr.php>

217.2   Le funzioni definite dall'utente

Un modo molto semplice di schematizzare il concetto di funzione è pensare ad una scatola che permette tramite due fori di inserire ed estrarre dei valori. All'interno della scatola può essere utilizzato qualunque costrutto messo a disposizione dal linguaggio, ecco perchè si parla di "sotto-programmi". Lo schema di figura 217.1 può essere di aiuto.

Figura 217.1. Il blocco di programma principale contiene due scatole (funzioni) che ricevono due valori e restituiscono in un caso la somma, in un altro la differenza.

figure/brdp_funzione_scatola

L'esempio classico è quello di una semplice funzione di saluto:

0  <?
1    //---------------- Definizione delle funzioni
2
3    function saluto($ora){
4
5      /*
6         Questa funzione genera un messaggio di saluto 
7         in base al valore della variabile $ora passatagli
8         che contiene l'ora, con valore tra 0 e 24
9      */
10
11     if (5 < $ora && $ora <= 12){
12        echo "Buon Giorno."; 
13     }elseif(12<$ora && $ora <= 18){
14        echo "Buon Pomeriggio.";
15     }elseif(18<$ora && $ora <= 24){
16        echo "Buona Sera!";
17     }else{
18        echo "Guarda che razza di ora è! Ma quando dormi?!";
19     }
20   }
21
22
23   //---------------- Programma principale
24
25   $orario = date("H");  // estraggo l'ora attuale
26
27   // Richiamo la funzione e ci aggiungo del testo...
28
29   saluto($orario);
30   echo " Come va oggi?!?";
31
32   // non serve riscrivere il codice posso inserire 
33   // il saluto con una sola RIGA di codice!!!
34
35   echo "<br><br> Ancora un saluto: "; saluto($orario);
36 ?>

Lo script è costituito da una parte contenente le dichiarazioni delle varie funzioni, nel caso specifico una sola, e dal programma principale che le richiama una o più volte. Come prima cosa è importante eseminare la sintassi per la dichiarazione delle funzioni.

  function nome_funzione(variabile_1, variabile_2, .... , variabile_n){

     istruzioni funzione

     return valore se necessario

  }

Il costrutto function segna l'inizio della dichiarazine, subito dopo va assegnato un nome che deve essere unico nel programma, non possono esserci più funzioni aventi lo stesso nome, tra parentesi tonde è possibile elencare le variabili, se esistono, che devono essere fornite alla funzione, se sono più di una vanno separate da una virgola (,). Il corpo della funzione è, infine, contenuto tra parentesi graffe ({...}).

Una volta dichiarata, la funzione, può essere richiamata tutte le volte che si vuole, è questo il vantaggio che si ha nel suddividere il lavoro in piccoli problemi e a risolverli con piccoli e semplici sotto-programmi da richiamare ogni volta che se ne ha bisogno.

Come detto la funzione può restituire dei valori, dunque quando richiamata può essere vista come una variabile contenente dei valori. Se si modifica l'esempio precedente come riportato di seguito, la funzione non scriverà nulla sullo schermo ma valorizzerà tramite il comando return il nome della funzione, esso potrà essere visualizzato, assegnato ad un'altra variabile, ecc... Proprio come fosse una variabile.

0 <?
1    //---------------- Definizione delle funzioni
2 
3    function saluto($ora){
4
5      /*
6         Questa funzione genera un messaggio di saluto 
7         in base al valore della variabile ricevuta $ora
8         che contiene l'ora con valore tra 0 e 24
9         e lo restituisce al programma principale tramite 
10        l'istruzione "return"
11     */
12
13     if (5 < $ora && $ora <= 12){
14        return "Buon Giorno."; 
15     }elseif(12<$ora && $ora <= 18){
16        return "Buon Pomeriggio.";
17     }elseif(18<$ora && $ora <= 24){
18        return "Buona Sera!";
19     }else{
20        return "Guarda che razza di ora è! Ma quando dormi?!";
21     }
22   }
23
24   //---------------- Programma principale
25
26   $orario = date("H");
27
28   // Richiamo la funzione e ci aggiungo del testo...
29
30   $msg = saluto($orario);      // assegno il valore della funzione
31   echo $msg." Come va oggi?!?";
32
33   // una sola RIGA di codice CONCATENATO come fosse una variabile
34
35   echo "<br><br> Ancora un saluto: ".saluto($orario);  
36 
37 ?>

Le modifiche adottate nelle righe 14, 16, 18, 20 provvedono tramite il comando return ad assegnare un valore al nome della funzione invece di visualizzarlo sullo schermo. Di conseguenza cambia il modo di manipolare la funzione al momento della chiamata, infatti, in questo modo ritorna un valore che può essere trattato come una semplice variabile. Nella riga 30 viene assegnato il valore restituito dalla funzione ad un'altra variabile, mentre nella riga 35 viene concatenato in una stringa.

A questo punto si potrebbe avere la necessità di scegliere se far visualizzare il messaggio direttamente dalla funzione o farlo ritornare come valore. Complicando leggermente l'esempio si può risolvere il problema. Una semplice soluzione è quella di passare una seconda variabile, che a seconda del suo stato (vero o falso) fa comportare la funzione in due modi diversi.

0  <?
1    //---------------- Definizione delle funzioni
2  
3    function saluto($ora, $modo){
4 
5      /*
6         Questa funzione genera un messaggio di saluto 
7         in base al valore della variabile ricevuta $ora
8         che contiene l'ora con valore tra 0 e 24
9         e lo restituisce al programma principale tramite 
10        l'istruzione "return" se $modo è falso, se è vero 
11        ne visualizza il valore.
12     */
13
14     if (5 < $ora && $ora <= 12){
15        $msg = "Buon Giorno."; 
16     }elseif(12<$ora && $ora <= 18){
17        $msg = "Buon Pomeriggio.";
18     }elseif(18<$ora && $ora <= 24){
19        $msg = "Buona Sera!";
20     }else{
21        $msg = "Guarda che razza di ora è! Ma quando dormi?!";
22     }
23
24     // controllo sul flag $modo.
25     if($modo){
26       echo $msg;
27     }else{
28       return $msg;
29     }
30
31   }
32
33   //---------------- Programma principale
34
35   $orario = date("H");
36   $modo = false;
37
38   // Richiamo la funzione e ci aggiungo del testo...
39   $msg = saluto($orario, $modo);
40   echo $msg." Come va oggi?!?"."<br><br>";
41
42   // Adesso posso anche farlo scrivere direttamente, ecco come:
43   saluto($orario,1);
44 ?>

Adesso la funzione si aspetta due parametri, il primo serve a generare il messaggio di saluto, il secondo (righe 25-29) a determinare il comportamento della funzione. Se cambia la dichiarazione deve cambiare anche la chiamata alla funzione, infatti, nelle righe 39 e 43 vengono passati i due parametri e la funzione si comporta di conseguenza.

Quando si richiama una funzione non importa il nome delle variabili che gli vengono fornite, quello che importa è l'ordine con cui esse vengono elencate.

Dunque i valori passati alla funzione andranno nelle variabili locali (della funzione) definite al momento della dichiarazione della stessa. Nell'esempio seguente viene approfondito questo aspetto tramite una funzione che genera e visualizza una scheda informativa di un potenziale utente.

0  <?
1    //---------------- Definizione delle funzioni
2 
3    function scheda($nome, $cognome){
4
5      /*
6        Questa funzione ha lo scopo di chiarire il concetto di
7        variabile locale e globale. Fare inoltre attenzione 
8        all'ordine con cui sono passate le variabili 
9      */
10
11     global $tel;
12
13     echo "<br>Scheda informativa utente: <br><br> ";
14     echo "<br>Nome: ".$nome;
15     echo "<br>Cognome: ".$cognome;
16     echo "<br>Telefono: ".$tel;
17     echo "<br>e-mail: ".$email;
18     echo "<br><br>-----------------------<br>";
19   }
20
21   //---------------- Programma principale
22
23   $nome = "Gianluca";
24   $cognome = "Giusti";
25   $tel = "06/66666666";
26   $email = "brdp @ urcanet.it";
27  
28   // richiamo la funzione che genera la scheda.
29   scheda($nome, $cognome);
30
31   // il nome delle variabili non importa! Importa invece l'ordine
32   // con cui vengono passate alla funzione! Ecco la prova:
33   scheda($cognome, $nome);
34 ?>

Come detto in principio, le funzioni sono dei piccoli programmi a se stanti, dunque le variabili utilizzate al loro interno, dette "variabili locali", non hanno lo stesso valore di quelle utilizzate nel programma principale, dette "variabili globali" anche se nominate allo stesso modo. Si può dire che sono variabili diverse. Un modo per far coincidere le variabili locali e globali è passare le variabili globali come argomento della funzione, proprio come fatto negli esempi precedenti. Un secondo metodo, è l'utilizzo del comando global. Nella riga 11 dell'esempio precedente viene utilizzato per "catturare" il valore della variabile globale $tel all'interno della funzione.

Il risultato dell'ultimo programma è simile a:

   Scheda informativa utente:

   Nome: Gianluca
   Cognome: Giusti
   Telefono: 06/66666666
   e-mail:

   -----------------------

   Scheda informativa utente:

   Nome: Giusti
   Cognome: Gianluca
   Telefono: 06/66666666
   e-mail:
 
   -----------------------

Come prima cosa va notata l'assenza dell'indirizzo e-mail, questo dipende dal fatto che la variabile $email non è stata fornita in alcun modo alla funzione quindi al suo interno non è valorizzata. Al contrario le altre variabili sono valorizzate, $nome e $cognome vengono passate al momento della chiamata mentre la variabile $tel viene associata a quella globale.

L'utilizzo di global non è consigliabile dal momento che ogni modifica alla variabile utilizzata come globale all'interno della funzione si riperquote anche nel programma principale. Se non si hanno motivi particolari non ha senso utilizzare questo metodo.

Un ottimo esercizio per l'utente è la verifica di quanto appena detto. Modificare l'ultimo esempio al fine di dimostrare che le modifiche alla variabile $tel effettuate all'interno della funzione si riperquotono anche nel programma principale, mentre eventuali modifiche alle variabili passate come argomento all'interno della funzione non hanno effetto nel programma principale.

Per i più esperti la situazione è simile al passaggio di variabili per "valore" o per "riferimento".

La funzione, inoltre, viene richiamata due volte invertendo l'ordine dei parametri a dimostrazione che il nome delle variabili non ha alcun importanza ma quello che importa è l'ordine con cui vengono dichiarate e passate al momento della chiamata.

In conclusione il modo migliore e più elegante per realizzare la scheda utente dell'esempio è fornire tutti i dati necessari alla funzione come parametri della chiamata.

0  <?
1    //---------------- Definizione delle funzioni
2
3    function scheda($nome, $cognome, $tel, $email){
4
5      // Il modo più corretto è il passaggio delle variabili
6      // Salvo casi particolari in cui si è obbligati ad usare il global
7
8      echo "<br>Scheda informativa utente: <br><br> ";
9      echo "<br>Nome: ".$nome;
10     echo "<br>Cognome: ".$cognome;
11     echo "<br>Telefono: ".$tel;
12     echo "<br>e-mail: ".$email;
13     echo "<br><br>-----------------------<br>";
14   }
15
16
17   //---------------- Programma principale
18
19   $nome = "Gianluca";
20   $cognome = "Giusti";
21   $telefono = "06/66666666";
22   $posta_elettronica = "brdp @ urcanet.it";
23  
24   // richiamo la funzione che genera la scheda. I nomi non contano!
25   scheda($nome, $cognome, $telefono, $posta_elettronica);
26
27 ?>

Uno degli aspetti più importanti di un sito Internet è l'estetica ed è anche la parte che viene rinnovata più di frequente. Si pensi alla necessità di elencare degli oggetti secondo particolari vesti grafiche, utilizzando una funzione è possibile modificare varie pagine, in cui essa viene richiamata, modificando una sola porzione di codice. Un altro esempio è dato dai siti in cui è possibile personalizzare la formattazione dei dati tramite la scelta di modelli predefiniti, in questo caso la funzione potrebbe ricevere un parametro in più che rappresente il modello, oppure si potrebbero implementare varie funzioni che formattano i medesimi dati in modo differente.

Come conclusione si può senza dubbio affermare che un programma strutturato è molto più leggibile ed elegante di uno costituito da un unico blocco di codice spesso incomprensibile.

In fine va notato che ci sono delle operazioni che vengono ripetute spesso nel lavoro di tutti i giorni, ad esempio formattazione della data in vari formati, connessione e interrogazioni di basi di dati, paginazione di elenchi, gestione di immagini, upload di file, ecc... La cosa più intelligente è creare dei file, paragonabili a librerie, contenenti le dichiarazioni delle funzioni più utilizzate, a questo punto basterà includere tali "librerie" in cima agli script in modo da poter richiamare le funzioni senza dovrele dichiarare ogni volta. Ancora più corretto è la creazione di "librerie" contenenti delle classi con cui poter dichiarare dei veri e propri oggetti ma questo verrà spiegato nella sezione dedicata alla programmazione avanzata.

Un esercizio interessante lasciato al lettore è quello di implementare una funzione chiamata isint($var), supponendo che non esista la funzione già vista is_integer(), che utilizzando gettype() restituisca un valore vero se la variabile passata è un intero o falso se la variabile è di un altro tipo.

217.3   Le funzioni ricorsive

Il PHP permette di richiamare le funzioni in modo ricorsivo, ovvero è possibile richiamare una funzione dal suo interno. Un classico esempio applicativo di questa tecnica è il calcolo del fattoriale. Come noto il fattoriale di un numero intero positivo n (indicato come n!) è pari a n*(n-1)*(n-2)*...*(n-(n-1)). Ad esempio:

5! = 5*4*3*2*1 = 120

Ecco come risolvere il problema con l'utilizzo di una funzione ricorsiva:

0<html><body>
1  <?
2   //---------------- Definizione delle funzioni
3
4   function fattoriale($numero){
5
6     if($numero <= 1){
7       return 1;   // abbandona la ricorsione
8     }else{
9       return $numero*fattoriale($numero-1);  //la funzione richiama se stessa
10    }
11
12  }
13
14
15  //---------------- Programma principale
16
17  echo "<br>Calcolo del fattoriale:<br>";
18
19  for($i=-2; $i<=10; $i++){
20    echo "<br>Il fattoriale di $i è: ".fattoriale($i);
21  }
22
23 ?>
24
25 </body></html>

All'interno della dichiarazione, riga 9, viene richiamata la funzione stessa passandogli il numero decrementato di uno. Questo perchè n! = n*(n-1)! = n*(n-1)*(n-2)! e così via... Il fattoriale di 0 è pari ad 1 per definizione. Per semplificare il controllo si è stabilito che il fattoriale di un numero negativo è pari ad 1 anche se non è corretto matematicamente.

L'attenzione non deve essere focalizzata sull'aspetto matematico ma sul fatto che la funzione nel programma principale viene richiamata una sola volta. Ancora più importante in problemi di questo genere è la definizione di una condizione di arresto, in questo caso quando il numero passato alla funzione è <=1 la funzione abbandona la ricorsione e restituisce valore pari ad 1. Se si sbaglia o si tralascia la condizione di uscita il programma potrebbe entrare in un ciclo infinito e non smetterebbe mai l'esecuzione.

Programmare in PHP --- Copyright © 2001-2002 Gianluca Giusti --  brdp @ urcanet.it

Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome l_utilizzo_delle_funzioni_in_php.html

[successivo] [precedente] [inizio] [fine] [indice generale] [violazione GPL] [translators] [docinfo] [indice analitico]