Cicli iterativi: while, do-while, for, foreach

Cicli iterativi in PHP: while, do-while, for e foreach

I cicli iterativi sono simili alle istruzioni condizionali in quanto la riga successiva di codice da eseguire dipende dal risultato di una condizione (true o false).

I cicli differiscono però dalle istruzioni condizionali in quanto il codice del ciclo può essere eseguito diverse volte nel caso la condizione risulti vera.

PHP mette a disposizione quattro costrutti iterativi, più due istruzioni per poter modificare il comportamento di un ciclo.

While

Il primo costrutto che andiamo a vedere è il while. La sua sintassi è molto semplice e simile a quella dell'istruzione if perché verifica il risultato di una condizione e, a seconda che questo sia true o false, viene eseguito il blocco di codice associato.

while (expr)
    statement

Dopo che il contenuto del ciclo è stato eseguito, viene verificata nuovamente la condizione e, se questa risulta false, il ciclo termina e PHP procede con la prima riga successiva al while, altrimenti esegue nuovamente il contenuto del ciclo fino a quando la condizione diventa false.

Di seguito è mostrato un esempio

<?php
$money = 10;

while ($money > 0) {
    echo "Valore di \$money = $money\n";
    $money--;
}

Il programma stampa in sequenza il valore di $money decrementato di una unità ad ogni iterazione. L'istruzione alla riga 6 permette al ciclo di terminare dopo 10 iterazioni, ossia quando $money sarà pari a zero.

Nota: se viene utilizzata una condizione che non risulta mai false, il ciclo continuerà all'infinito senza generare errori. Questa è una cosa da tener presente quando si utilizzano i cicli.

Do-while

Il funzionamento del costrutto do-while è simile a quello del while, con l'unica differenza che la condizione viene verificata alla fine, dopo che è stata eseguito il codice dell'iterazione. La sua sintassi è la seguente:

do {
    statement;
} (expr);

Ciò comporta una piccola differenza rispetto al while, in quanto il contenuto del ciclo verrà eseguito almeno una volta, anche se la condizione risulta false.

L'esempio seguente mostra il funzionamento del do-while

<?php
$attempts = 1;

do {
    $coinFlip = random_int(0,1); // 0 testa 1 croce
    echo "Lancio n. $attempts: $coinFlip\n";
    $attempts--;
} while ($attempts < 10);

Con lo script precedente abbiamo simulato il lancio di una monetina con la funzione random_int() di PHP, la quale genera numeri interi casuali compresi tra i due estremi passati come parametro.

Anche in questo caso l'istruzione di decremento ci consente di uscire dal ciclo, evitando un loop infinito.

For

A differenza del while Il ciclo for permette di specificare il numero di iterazioni. La sua sintassi è la seguente:

for (expr1; expr2; expr3)
    statement;

Vediamo il significato di ciascuna istruzione:

  1. expr1 è l'istruzione eseguita solo all'inizio del ciclo. Rappresenta il contatore delle iterazioni e viene inizializzata con un valore intero.
  2. expr2 è la condizione eseguita all'inizio di ogni iterazione. Controlla se il contatore delle iterazioni è stato superato e in caso positivo termina il ciclo.
  3. expr3 è l'istruzione eseguita al termine di ogni ciclo e garantisce che il valore di expr1 venga cambiato ad ogni iterazione.
  4. statement è il blocco di codice eseguito ad ogni iterazione. Nel caso il blocco contenga più istruzioni queste vanno racchiuse tra parentesi graffe.

Nota: le parentesi graffe possono essere omesse nel caso il blocco di codice sia composto da una sola istruzione, ma per chiarezza è buona prassi aggiungerle sempre.

Di seguito è mostrato un esempio di utilizzo

<?php
$colors = ['blu', 'giallo', 'verde', 'rosso', 'bianco'];

for ($i = 0; $i < count($colors); $i++) {
    echo "$colors[$i]\n";
}

/* Output

blu
giallo
verde
rosso
bianco

*/

La prima istruzione assegna il valore zero alla variabile $i. Con questa variabile possiamo accedere agli elementi dell'array $colors. Ricordiamoci che il primo elemento di un array ha indice numerico uguale a 0.

Successivamente viene verificata la condizione $i < count($array), in cui viene calcolata la dimensione dell'array e confrontata col valore del contatore $i. Dato che la condizione risulta vera, viene eseguito il blocco di codice racchiuso tra le graffe, ovvero la stampa a video dell'elemento corrente.

Infine viene eseguita l'istruzione di incremento $i++. Adesso $i è uguale a 1 e si ripetono nuovamente tutti i passaggi fino a quando la condizione diventa false, ovvero quando il valore di $i sarà uguale a 5.

In questo esempio abbiamo utilizzato la funzione count() di PHP, la quale restituisce la dimensione di un array. Dato che l'istruzione condizionale viene verificata ad ogni ciclo, la dimensione dell'array viene calcolata per ben 5 volte.

Possiamo ottimizzare il nostro codice semplicemente memorizzando questo valore in una variabile, evitando di sprecare preziosi cicli di CPU e velocizzando l'esecuzione del programma.

<?php
$colors = ['blu', 'giallo', 'verde', 'rosso', 'bianco'];

for ($i = 0, $count = count($colors); $i < $count; $i++) {
    echo "$colors[$i]\n";
}

/* Output

blu
giallo
verde
rosso
bianco

*/

Nota: in questo caso l'ottimizzazione ha riguardato pochi elementi, ma nel caso dovessimo ciclare un array con migliaia di elementi, potremmo ottenere un significativo miglioramento in ottica ottimizzazione.

Foreach

Il costrutto foreach è comodo quando vogliamo eseguire cicli su array associativi, array multidimensionali, oppure oggetti. Esistono due versioni di foreach:

foreach ($array as $value)
    statement;

e

foreach ($array as $key => $value)
    statement;

Ad ogni ciclo il valore dell'elemento corrente dell'array viene assegnato a $value e il puntatore dell'array viene spostato di una posizione, nell'elemento successivo. Le iterazioni terminano quando il puntatore sarà arrivato all'ultimo elemento.

La prima versione viene utilizzata per leggere gli elementi di un array, la seconda versione è utile nel caso di array associativi, in cui vogliamo accedere alle chiavi dell'array.

Vediamo subito un esempio per entrambe le versioni

<?php
$colors = ['blu', 'giallo', 'verde', 'rosso', 'bianco'];

// Prima versione

foreach ($colors as $color) {
    echo "$color\n";
}

// Seconda versione

$days = [
    'lun' => 'lunedì',
    'mar' => 'martedì',
    'mer' => 'mercoledì', 
    'gio' => 'giovedì', 
    'ven' => 'venerdì', 
    'sab' => 'sabato', 
    'dom' => 'domenica'
];

foreach ($days as $key => $value) {
    echo "$key = $value\n";
}

Break e continue

L'istruzione break consente di terminare immediatamente l'esecuzione di un ciclo, passando il controllo all'istruzione successiva:

<?php
$colors = ['blu', 'giallo', 'verde', 'rosso', 'bianco'];

foreach ($colors as $color) {
    if ($color == 'verde') {
        break;
    }
    
    echo "$color\n";
}

/* Output

blu
giallo

*/

L'istruzione continue consente di saltare una o più iterazioni, senza interrompere l'esecuzione del ciclo:

<?php
$colors = ['blu', 'giallo', 'verde', 'rosso', 'bianco'];

foreach ($colors as $color) {
    if ($color == 'giallo' || $color == 'rosso') {
        continue;
    }
    
    echo "$color\n";
}

/* Output 

blu
verde
bianco

*/

Sintassi alternativa

Come per le istruzioni condizionali, anche per i costrutti iterativi è possibile sfruttare la sintassi alternativa. La parentesi graffa di apertura per while, for e foreach è sostituita dal carattere dei due punti (:), mentre la parentesi di chiusura rispettivamente con endwhile, endfor e endforeach.

Vediamo un esempio di utilizzo per il foreach:

<?php
$menu = [
    'home' => "https://www.sito.it",
    'about' => "https://www.sito.it/about",
    'blog' => "https://www.sito.it/blog",
    'contatti' => "https://www.sito.it/contatti"
];
?>
<html>
<body>
    <ul>
        <?php foreach ($menu as $key => $value):?>
        <li><a href="<?php echo $value;?>"><?php echo $key;?></a></li>
        <?php endforeach;?>
    </ul>
</body>
</html>