25 – 26 – 27 -28 Funzioni
un esempio semplice di funzione:
la prima parte è la definizione della funzione, tra sole tonde gli argomenti (non obbligatori) separati dalla virgola, tra le graffe i comandi da eseguire:
function p($testo,$stili="") { echo "<p style='$stili'> $testo </p> \n"; }
La seconda è l’invocazione (il richiamo) a tale funzione:
p("ecco il primo paragrafo"); p("qui il secondo paragrafo","background-color:pink; height:30px;");
Nella prima funzione non viene selezionato nessun secondo argomento, che abbiamo reso facoltativo con $stili=””, quindi viene assegnato il valore di default, che in questo caso è nullo.
Un esempio nel quale dichiaro una variabile con valore e poi all’interno della funzione cambio il valore alla variabile:
<?php $messaggio = "Messaggio originale"; p("ecco il primo paragrafo"); p("qui il secondo paragrafo","background-color: pink; height:30px;"); function p($testo,$stili="") { echo "<p style='$stili'> $testo </p> \n"; $messaggio = "Scerzetto !"; } echo $messaggio; ?>
In questo caso, con l’ultimo echo che stampa il valore della variabile $messaggio, non mi verrà restituito il valore passato dalla funzione ma quello dichiarato esternamente ($messaggio=”Messaggio originale”).
Per far si che la funzione possa cambiare il valore di una variabile esterna, dovrò usare il comando global.
<?php $messaggio = "Messaggio originale"; p("ecco il primo paragrafo"); p("qui il secondo paragrafo","background-color: pink; height:30px;"); function p($testo,$stili="") { global $messaggio; echo "<p style='$stili'> $testo </p> \n"; $messaggio = "Scerzetto !"; } echo $messaggio; ?>
Anche se l’uso di global ci riserva sicurezza in più, esiste un metodo ancora più sicuro, cioè quello del passaggio dei valori per indirizzo, anzichè quello per valore. Questo può essere fatto quando chiamo una funzione e nel primo argomento, anzichè assegnare un valore,
p (“ecco il primo paragrafo”);
gli assegno una variabile:
p ($messaggio);
A questo punto non viene modificato il valore di $testo ma di $messaggio che sarà una copia di $testo.
Per usare il passaggio per indirizzo, dovrò inoltre aggiungere nella definizione della funzione una & davanti all’argomento che voglio passare per indirizzo, quindi:
function p (&$testo,$stili=””) Qualsiasi modifica fatta a $testo si ripercuoterà anche su $messaggio.
Le variabili definite dentro le funzioni sono chiamate variabili locali (tranne che se uso la keyword global) e perdono il loro valore una volta usciti dallo script della funzione. Ecco un esempio:
<?php $nl="<br />"; $contatore = 0; while ($contatore < 10) { piu_saluto_e_meglio_e(); $contatore++; } function piu_saluto_e_meglio_e() { global $nl; //questa variabile agisce in esterno if (!isset($saluto)) $saluto="Ciao"; else $saluto = $saluto . "Ciao"; echo $saluto . $nl; } ?>
In questo caso la parte dell’else dentro la funziona non verrà mai eseguita, perchè ad ogni ripetizione del ciclo while, il programma non troverà mai $saluto settata.
È comunque possibile far mantenere un valore ad una variabile all’interno della funzione, aggiungendo la keyword static davanti al nome della funzione:
<?php $nl="<br />"; $contatore = 0; while ($contatore < 10) { piu_saluto_e_meglio_e(); $contatore++; } function piu_saluto_e_meglio_e() { global $nl; //questa variabile agisce in esterno static $saluto; if (!isset($saluto)) $saluto="Ciao"; else $saluto = $saluto . "Ciao"; echo $saluto . $nl; } ?>
In questo caso la variabile è di tipo statico e mantiene il suo valore anche fuori dalla funzione. Qualora assegnassimo un valore alla variabile statica (static $saluto=”Topolino”), questo valore verrebbe letto solo alla prima esecuzione della funzione e non lo manterrebbe ad ogni ciclo.
Una funzione non deve per forza ricevere tanti parametri quanti sono gli argomenti definiti nella funzione, ma il numero può variare in base a quelle passate:
<?php generacheckbox ("Menta", "Limone", "Banana"); function generacheckbox () { $listaParametri = func_get_args(); $numeroParametri = func_num_args(); for ($parametro=0; $parametro<$numeroParametri; $parametro++) echo $listaParametri[$parametro] . "<input type='checkbox' name='gustiGelato[]'" . "value='$listaParametri[$parametro]' />"; } ?>
La prima cosa da notare è la funzione predefinita func_get_args che pesca gli argomenti inseriti e restituisce un array di valori. func_num_args, restituisce il numero di argomenti (menta sarà 1, limone 2). Interessante è il name del tag <input> che viene inserito come un array e il parametro andrà nelle parentesi quadre (name=’gustiGelato[]’) ed eventualmente passato ad un ipotetico submit. Se non viene specificato nessun parametro, il ciclo for si ferma perchè 0 non è minore di 0, quindi il programma funziona perfettamente.
Abbiamo già la funzione rand che genera un numero casuale. Ipotizzando di simulare 20 lanci di dadi, farò uscire un numero casuale compreso tra 1 e 6 .
<?php $nl="<br />"; for ($numero_lanci=1; $numero_lanci<=20; $numero_lanci++) echo rand(1,6) . $nl; ?>
Se invece vogliamo barare e far uscire un numero più volte degli altri per esempio il 3, farò in questo modo:
<?php $nl="<br />"; for ($numero_lanci=1; $numero_lanci<=20; $numero_lanci++) echo dado_tarocco(3) . $nl; function dado_tarocco($faccia_taroccata) { $estratto = rand(1,10); if ($estratto<=6) return $estratto; else return $faccia_taroccata; } ?>
In questo caso creo la funzione dado_tarocco, e gli faccio generare un numero casuale compreso tra 1 e 10, se il numero è minore di 6, lo restituisce (return) e lo passa come valore della funzione, altrimenti restituisce la variabile (by value) dell’argomento che prende l’argomento specificato nell’uso della funzione echo dado_tarocco(3).
Se volessimo avere più di un valore, tipo avere 2 dadi (questa volta senza barare), facciamo restituire un array:
<?php $nl="<br />"; function coppia_dadi() { return array(rand(1,6) , rand(1,6) ); } for($numero_lanci=1; $numero_lanci<=20; $numero_lanci++) { $due_dadi = coppia_dadi(); echo $due_dadi[0]. " - ". $due_dadi[1].$nl; } ?>
La funzione coppia_dadi restituisce un array con 2 numeri casuali compresi tra 1 e 6 e viene memorizzata dentro $due_dadi.
Supponiamo invece che di mercoledì vogliamo barare più del solito:
<?php $nl="<br />"; function dado_tarocco($faccia_taroccata) { $estratto = rand(1,10); if ($estratto<=6) return $estratto; else return $faccia_taroccata; } function dado_molto_tarocco($faccia_taroccata) { $estratto = rand(1,14); if ($estratto<=6) return $estratto; else return $faccia_taroccata; } $oggi= getdate("wday"); if ($oggi==3) // 0=domenica, 1=lunedì ... $usa_questa="dado_molto_tarocco"; else $usa_questa="dado_tarocco"; for ($numero_lanci=1; $numero_lanci<=20; $numero_lanci++) { echo $usa_questa(3) . $nl; } ?>
Ho creato 2 funzioni, dado_tarocco() e dado_molto_tarocco() la prima solita che sceglie un numero tra 1 e 10 e l’altra che ne sceglie uno tra 1 e 14, quindi le possibilità che esca sono più alte. Poi memorizzo il numero corrispondente al giorno nella variabile $oggi (3 è mercoledì). Se il numero del giorno è uguale a 3 (mercoledì), memorizzo il nome della funzione dado_molto_tarocco dentro la variabile $usa_questa, altrimenti memorizzo il nome dell’altra funzione (dado_tarocco). La particolarità sta che nell’ultimo echo uso la funzione richiamandola con una variabile a cui è assegnato il nome di quella funzione (echo $usa_questa(3) )