Come già successo per gli altri capitoli di questa guida, anche il concetto di closure non è nuovo, ma è stato introdotto in PHP 5.3.

Il suo utilizzo principale è sicuramente quello usare una closure come funzione di callback. In sostanza, una closure è una funzione anonima, cioè una funzione che viene “usata al volo” senza essere stata dichiarata in precedenza.
Partiamo subito con un po’ di codice:

<?php
      $array = ['Lamborghini', 'Ferrari', 'Pagani', 'Maserati'];
      array_walk($array, function(&$v, $k) {
        $v = "La $v spacca";
      });
      print_r($array);

 

In questo esempio, passiamo come secondo parametro della funzione array_walk , una closure: in pratica utilizziamo una funzione che verrà creata al volo solo per questo scopo. Da notare che alla funzione passiamo due parametri, uno dei quali $v  per riferimento: esso sarà legato cioè al valore originale dell’array. Significa che modificandolo modificheremo direttamente il valore dell’array,

Possiamo anche assegnare una funzione ad una variabile, proprio come se fosse un normale valore:

<?php
$var = function($testo) {
    return "Sono una funzione anonima";
};
print_r($var());

// Sono una funzione anonima

E naturalmente utilizzare dei parametri:

<?php
$var = function($testo) {
    return "Sono una funzione anonima";
};

print_r($var("bellissima"));

// Sono una funzione anonima bellissima

Non dimentichiamoci che la funzione va chiusa con ;  proprio come se alla variabile assegnassimo un valore!

Capite le basi, veniamo ad uno degli aspetti che più può portare a confusione, e cioè come le funzioni anonime riescono ad utilizzare le variabili del “genitore” che le ospita. In PHP questo comportamento si raggiunge utilizzando il costrutto use . La sintassi è questa:

function() use ($variabile) {

    /* codice */

}

Nell’esempio che segue, la funzione anonima assegnata a $func  utilizza la variabile $param del suo genitore, cioè quella dichiarata nella funzione saluta() nel rigo subito sopra e NON quella globale.

<?php

$param  = 'Alessandro';

function saluta() {
    $param = "Luca";
    $func  = function() use ($param) {
        echo "Ciao" . $param;
    };
    $func();
}

saluta();

// Ciao Luca

Questo codice stamperà quindi Ciao Luca , proprio perché la nostra closure ha utilizzato il $param  nel cosiddetto parent scope.

Vediamo un esempio più complesso, nel quale passeremo il parametro alla funzione anonima per riferimento:

<?php

function saluta() {
    $param = "Luca";
    $func  = function() use (&$param) {
        $param = "Antonio";
    };
    $func();
    echo "Ciao" . $param;
}

saluta();

// Ciao Antonio

Dato che abbiamo utilizzato &$param , cioè utilizzato il parametro per riferimento, la funzione anonima ha fatto accesso diretto a $param = “Luca”; e ne ha modificato il valore.

Arrow functions

Le arrow function sono state introdotte nella versione 7.4, e sono in pratica delle funzioni anonime scritte con una sintassi più concisa.

Vediamole subito in azione:

<?php

    $nome = "Paolo";
    $saluta = fn() => "Ciao " . $nome;
    $saluta();

    //Ciao Paolo

?>

La sintassi di una arrow function è molto breve: fn() => [valore restituito] . Questo ci dice che a tutto quello “a destra” di =>  viene anteposto virtualmente return .

Da notare che le arrow function accedono automaticamente alle variabili del “global scope”. Nel nostro codice, quindi, la funzione accede al contenuto di $n , stampando a schermo “Ciao Paolo”.