12. Strutture di controllo

PHP ci mette a disposizione diverse strutture di controllo, che possiamo dividere principalmente in due grandi categorie : le strutture condizionali e quelle iterative.

Le strutture condizionali, ci consentono di eseguire percorsi diversi in casi specifici in fase di esecuzione, mentre le strutture iterative, ci permettono di eseguire lo stesso pezzo di codice per un determinato numero di volte, dipendente dalla condizione specificata.

Vediamo ora le strutture di controllo condizionali :

  • IF e ELSE - Struttura più comune presente in molti linguaggi
  • SWITCH - Costrutto molto simile a IF e ELSE, utile per creare strutture condizionali molto lunghe

E' possibile inserire una semplice IF, specificando il pezzo di codice da eseguire nel caso in cui la condizione venga soddisfatta, fra parentesi graffe. Le parentesi non sono necessarie qualora il codice da eseguire consista in una singola riga.

Se volete specificare del codice da eseguire, nel caso in cui la condizione della IF fallisca, è sufficiente accodare a quest'ultima un blocco ELSE. Se due condizioni non sono sufficienti, allora potete inserire fra la IF ed un'eventuale ELSE, dei blocchi ELSE IF, che al contrario del blocco ELSE, richiedono una condizione precisa.

Le istruzioni nel blocco ELSE quindi, verranno eseguite solo se falliscono le condizioni della IF e di tutte le ELSE IF che precedono il blocco ELSE. E' anche possibile omettere i blocchi ELSE e ELSE IF, a patto che ci sia sempre e per primo uno o più blocchi IF.
Vediamo qualche esempio :

$x = 5;

if ($x == 5) // Se $x è uguale a 5
	$x = 1;
else // altrimenti
	$x = 0;

echo $x; // stampa : 1

$stringa = "5";

if ($stringa === 5) // Se è uguale a 5 ed è un numero intero
	$stringa += 5;
else if ($stringa === "5") // Se è uguale a 5 ed è una stringa
	$stringa .= " gatti";
else if ($stringa == "pippo") // Se il valore è uguale a "pippo"
{
	// Qui usiamo le graffe perchè la "else if" deve ospitare più di una istruzione
	$stringa .= " e pluto ";
	$stringa .= strlen($stringa);
}
else
	$stringa = "errore";

echo $stringa; // Stampa : "5 gatti"

Ovviamente mettendo in fila solo blocchi IF, le condizioni verranno tutte controllate e se soddisfatte, saranno eseguiti tutti i blocchi di istruzioni corrispondenti, come nell'esempio seguente :

$a = 5;
$stringa = "x";

if ($a == 5)
	$stringa .= "5";
if ($a > 4)
	$stringa .= "x";

echo $stringa; // Stampa : "x5x"

Altra struttura di controllo condizionale, è la SWITCH, che specificato un parametro iniziale, ci consente di confrontarlo con una serie di valori, mediante la parola chiave case seguita dai due punti.
Si può separare un blocco case da un altro grazie all'istruzione break.

Anche qui non abbiamo un limite al numero di condizioni, in quanto dipende dalla memoria che la nostra applicazione ha a disposizione.
Oltre alla parola chiave case, è possibile usare il comando default, per specificare un blocco di codice da eseguire nel caso in cui tutte le case falliscano (equivalente di ELSE).

Una particolarità della struttura SWITCH, consiste nel confronto che verrà sempre e solo effettuato per valore, come con l'operatore ==, rendendola quindi inutile qualora sia necessario fare dei confronti di equivalenza (corrispondente operatore ===), che tengano conto sia del valore che del tipo di dato.

E' possibile però specificare, nella condizione dei singoli case, di utilizzare una comparazione di equivalenza, inserendo variabile ed operatore nella condizione, come per una IF o per una ELSE IF.

Un altra particolarità che rende versatile la SWITCH, è il cosiddetto metodo a cascata, che ci consente di scrivere un unico blocco di codice da eseguire al verificarsi di più condizioni.

Vediamo un esempio che includa tutto ciò che è stato detto finora sulla SWITCH :

$stringa = "50";

switch ($stringa)
{
	case 50: echo "Uguale a 50<br />";
	case $stringa === "50": echo "Equivalente a 50<br />";
		break;
	case $stringa > 10: echo "Maggiore di 10<br />";
		break;
	default: echo "Diverso da 50<br />";
		break;
}

L'esempio produce questo risultato.
Nei primi due case possiamo osservare l'effetto a cascata. Essendo stato omesso il break nel primo case, il controllo continua e finisce nel secondo case, dove viene esplicitamente utilizzato un controllo sull'equivalenza di $stringa, e infine la SWITCH si conclude.

Il terzo case non produce la stringa "Maggiore di 10", in quanto viene soddisfatto già il secondo case, che contenendo un break, pone fine alla serie di condizioni.

Parliamo ora delle Strutture di controllo iterative (o Cicli) che, come abbiamo detto prima, ci consentono di eseguire un determinato pezzo di codice un preciso numero di volte, o fino al fallimento di una data condizione.

PHP ci mette a disposizione 4 diversi tipi di Cicli :

  • FOR - Prende tre parametri : un indice, una condizione e un incremento.
  • WHILE - Prende un solo parametro : una condizione.
  • DO/WHILE - Prende un solo parametro : una condizione.
  • FOREACH - Prende due parametri : un array e un valore o chiave/valore.

Il ciclo FOR viene solitamente usato per gestire uno o più indici interi, spesso per scorrere uno o più array contemporaneamente ed effettuare particolari ricerche o ordinamenti in essi.

Non è necessario specificare tutti e 3 i parametri della FOR, ma omettendo la condizione si da vita ad un ciclo infinito, terminabile solo con un'istruzione break all'interno del ciclo.

Il primo parametro consiste nella dichiarazione ed inizializzazione di uno o più indici, o omettendolo in un punto e virgola.

Il secondo parametro invece è la condizione, che come per la IF può essere un'espressione più o meno articolata.

Infine il terzo parametro, deve essere l'incremento o decremento di uno o più indici, o anche questo come gli altri parametri, un semplice punto e virgola per la dichiarata omissione.

Vediamo subito qualche esempio di FOR :

for ($i = 0; $i < 10; $i++) echo $i; // Stampa : 0123456789

for ( ; ; )	echo "ciao"; // Stampa "ciao" all'infinito

Il ciclo WHILE, come già accennato, prende un solo parametro ossia una condizione, che farà eseguire il ciclo fino al suo fallimento.
Questo significa che possiamo riprodurre la FOR dell'esempio precedente, anteponendo al ciclo l'inizializzazione degli indici e mettendo a fine ciclo i vari incrementi/decrementi.

Il ciclo DO/WHILE invece, è una sorta di WHILE invertita, ossia esegue prima il codice all'interno e poi controlla la sua condizione. Vediamo qualche esempio :

$i = 0;

while ($i < 10)
{
	echo $i;
	$i++;
} // Stampa : 0123456789

$condizione = false;

$i = 0;

do {
	echo $i++;
} while ($condizione) // Stampa 0 e poi si ferma

Infine vediamo l'ultimo dei 4 cicli, la FOREACH.
Lo scopo principale di questo ciclo, è quello di eseguire un blocco di codice per ogni elemento contenuto nell'array specificato.

Ci sono due modi di usare una FOREACH, vediamone subito un esempio :

$array = array("uno", "due", "tre", "quattro", "cinque");

foreach ($array as $valore)
	echo $valore . "<br />";

foreach ($array as $chiave => $valore)
	echo "$chiave : $valore<br />";

La prima FOREACH produce questo risultato, mentre la seconda produce quest altro.

Il primo metodo viene solitamente usato nel caso di array normali, mentre il secondo per array associativi, ma potete usarli come preferite.

PHP ci fornisce altri due comandi per aumentare il controllo sui cicli : break e continue.

L'istruzione break, semplicemente interrompe il ciclo quando viene eseguita, mentre l'istruzione continue, obbliga il ciclo a saltare all'iterazione successiva senza completare le istruzioni presenti nell'iterazione corrente.

for ($i = 0; $i < 10; $i++)
{
	if ($i % 2)
	{
		echo "$i ... continue<br />";
		continue; // Istruzione CONTINUE
	}

	echo "$i ... non continue<br />";
}

Nell'esempio vediamo la prima IF controllare se l'indice $i è dispari, attraverso l'operatore modulo % (resto della divisione), e in tal caso richiama l'istruzione continue che fa saltare al ciclo tutte le istruzioni successive ad essa, procedendo con l'iterazione successiva.

Avremmo anche potuto costruire del codice equivalente, servendoci di un blocco IF ELSE, producendo il medesimo risultato.

Vediamo ora il codice senza l'istruzione continue, che produrrà invece sul browser questo risultato :

for ($i = 0; $i < 10; $i++)
{
	if ($i % 2)
		echo "$i ... continue<br />";

	echo "$i ... non continue<br />";
}

Vediamo ora un esempio veloce per illustrare meglio l'istruzione break.
Poniamo di voler interrompere il ciclo a metà della sua vita, impostando la preferenza attraverso una variabile esterna al ciclo.

$esterna = true;
$iterazioni = 10;

for ($i = 0; $i < $iterazioni; $i++)
{
	if ($esterna && ($iterazioni / 2) == $i)
		break;

	echo "$i<br />";
}

Il ciclo dell'esempio stamperà "0 1 2 3 4" e poi verrà interrotto dal break.

Vediamo infine le ultime strutture di controllo : exit e die.
Le due istruzioni in questione sono equivalenti, ed hanno lo scopo di interrompere l'intero script da qualsiasi posizione vengano chiamate, con un parametro aggiuntivo opzionale, che consiste in un messaggio da stampare sul browser prima della terminazione dello script.

Questi due comandi, non solo terminano lo script, ma interrompono l'intero flusso HTML, rendendole quindi particolarmente inappropriate per una gestione pulita degli errori, argomento che tratteremo più avanti in un capitolo interamente dedicato a questo.

Di seguito un esempio con l'istruzione die :

<html>
	<head>
		<title>Test</title>
	</head>

	<body>

		<h3>Test</h3>
<?php

	die("Errore irreversibile!");

?>
		<p>Alcuni diritti riservati - by pippo</p>
	</body>

</html>

L'esempio produce questo risultato. Il piè di pagina con i diritti d'autore non viene infatti stampato, in quanto die interrompe completamente il flusso dati (Sorgente pagina).