Callback e funzioni di ordine superiore in PHP
Una callback è una funzione che può essere passata come argomento ad un'altra funzione e quindi eseguita al suo interno. Questo consente di passare un comportamento personalizzato alla funzione chiamante, che può essere eseguito in base alle esigenze specifiche dell'applicazione.
Una callback può essere definita come una funzione anonima o come una funzione con un nome specifico. Questa può essere quindi passata come argomento alla funzione chiamante utilizzando il nome della funzione o una referenza alla funzione.
Cos'è una funzione di ordine superiore
Una funzione di ordine superiore è una funzione che accetta una o più funzioni come argomenti e/o restituisce una funzione come risultato.
Indice
Sintassi di una callback all'interno di una funzione di ordine superiore
Per spiegare la sintassi di una callback creeremo un piccolo esempio dove viene creata una funzione nominata fnA che passa come argomenti la funzione fnB con type hinting ed un altro argomento, questa funzione eseguirà la funzione fnB.
Creiamo una funzione fnC() che sta per fatti suoi.
Quando invochiamo la funzione fnA() passiamo in input come primo argomento la funzione fnC e come secondo argomento un numero.
La callback in questo esempio è fnB che si trova come argomento di fnA.
<?php
function fnA(callable $fnB, $parametro){
$fnB();
};
function fnC(){
echo "funzione eseguita ...";
};
fnA('fnC',10);
?>
// output: funzione eseguita ...
Esempio di Callback
In questo esempio, creiamo una funzione di ordine superiore calcoloValore() che accetta come argomenti un array specificato tramite type hinting array ed una funzione normale specificata tramite type hinting callable (se avremmo voluto passare una funzione anonima avremmo dovuto indicare closure come tipe hinting). L'esecuzione di questa funzione di ordine superiore restituisce la funzione passata come parametro fnCallBack() da eseguire sull'array $parametro passato come parametro all'interno della funzione calcoloValore().
Le funzioni sommaPari() e sommaDispari() prendono l'array passato in input e:
la funzione sommaPari() parte da 0 e finisce alla fine dell'array e incrementa di 2, aggiunge al totale (inizializzato da 0) il valore che trova all'interno dell'indice dell'array saltandone uno (incremento di $i += 2)
la funzione sommaDispari() parte da 1 e finisce alla fine dell'array e incrementa di 2, aggiunge al totale (inizializzato da 0) il valore che trova all'interno dell'indice dell'array saltandone uno (incremento di $i += 2)
<?php
// Callback e funzioni di ordine superiore
function calcoloValore(array $parametro, callable $fnCallBack){
return $fnCallBack($parametro);
};
// Creiamo una funzione che sommi tutti i numeri pari (in base alla posizione dell'indice)
function sommaPari($valori){
$totale = 0;
for($i = 0; $i < count($valori); $i += 2){
$totale += $valori[$i];
};
return $totale . "\n";
};
// Creiamo una funzione che sommi tutti i numeri dispari (in base alla posizione dell'indice)
function sommaDispari($valori){
$totale = 0;
for($i = 1; $i < count($valori); $i += 2){
$totale += $valori[$i];
};
return $totale . "\n";
};
echo calcoloValore([2,4,6,8,10,12],'sommaPari');
echo calcoloValore([2,4,6,8,10,12],'sommaDispari');
?>
/* output:
18
24
*/
Altro esempio di Callback e funzione di ordine superiore con usort()
<?php
// Creiamo un array contenente degli utenti
$utenti = [
['nome' => 'Donato', 'età' => 33, 'SpesaNoTax' => 40.97],
['nome' => 'Paolo', 'età' => 25, 'SpesaNoTax' => 81.96],
['nome' => 'Mario', 'età' => 35, 'SpesaNoTax' => 163.93],
];
/*
Usiamo la funzione usort come funzione di
ordine superiore (poichè accetta una funzione al suo interno)
per ordinare la lista degli utenti in base all'età
*/
usort($utenti, function ($a, $b) {
return $a['età'] <=> $b['età'];
});
/*
Con il ciclo foreach iteriamo sull'array $utenti e
per ogni utente calcoliamo la spesa comprensiva di iva.
Alla fine stampiamo il tutto.
*/
foreach($utenti as $utente){
$spesaTax = $utente['SpesaNoTax'] * 1.22;
echo $utente['nome'] . ' ha ' . $utente['età'] . ' anni ed oggi ha speso ' . round($spesaTax,2) . "\n";
}
?>