Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Le funzioni anonime di PHP

Come usare praticamente in PHP le funzioni anonime: le funzioni che non vengono legate a nessun identificatore specifico
Come usare praticamente in PHP le funzioni anonime: le funzioni che non vengono legate a nessun identificatore specifico
Link copiato negli appunti

Le “funzioni anonime” (Anonymous functions o Lambda functions) di PHP sono degli strumenti introdotti con la versione 5.3 di questo linguaggio per lo scripting server side che si caratterizzano per due peculiarità:

  1. non essere associate ad un nome, non necessitano di un namespace e non vengono definite attraverso di esso;
  2. poter essere impiegate come parametri per un’altra funzione.

Le funzioni richiamate da altre funzioni sono dette “funzioni di callback”, le funzioni anonime presentano l’indubbio vantaggio di non dover essere dichiarate prima di venire impiegate come parametri, esse necessitano infatti unicamente di un passaggio di argomenti.

È bene specificare che in PHP non sono disponibili delle funzioni anonime vere e proprie, ma delle imitazioni di esse, questo perché tale linguaggio non tratta le funzioni come “oggetti di prima classe” (first-class objects), cioè non permette che esse possano assolvere a determinati compiti come per esempio essere restituite sotto forma di valori da altre funzioni o essere assegnate a variabili.

In questa breve trattazione verranno proposti alcuni esempi pratici relativi all'utilizzo di questo particolare tipo di funzioni.

La funzione create_function()

Precedentemente alla versione 4.0.1 di PHP questo linguaggio non metteva a disposizione alcun supporto per le funzioni anonime, con tale release è stata invece introdotta la forse sotto-utilizzata funzione create_function() che ha fornito agli sviluppatori una forma embrionale di questi costrutti, in pratica, una chiamata ad essa genera una funzione denominata in modo casuale e ne restituisce il nome sotto forma di stringa, il suo compito è quindi quello di creare funzioni anonime.

Fondamentalmente a livello sintattico create_function() accetta due parametri:

  1.  una stringa che è argomento della funzione;
  2. un codice, che è poi il codice della funzione e che ne determina il valore di ritorno.

Un semplice esempio riguardante l'utilizzo di create_function() potrebbe essere il seguente:

<?php
// generazione della funzione
$pippo = create_function('$var', 'return $var*$var;');
// passaggio di un argomento alla funzione generata
$pippo(5);
?>

Nell'impiego di questa funzione è fondamentale tenere conto del fatto che entrambi i parametri di create_function() devono essere delimitati da apici singoli, in alternativa sarà necessario effettuare  l'escaping (cioè il quoting di un singolo carattere) del simbolo del dollaro, come nell'esempio seguente che ripropone quello introdotto in precedenza:

$pippo = create_function("$var", "return $var*$var;");

Senza l'escaping infatti, l'interprete del linguaggio leggerà $var come variabile $var e ne determinerà la sostituzione all'interno della stringa invece di lasciarla al suo interno.

Un esempio pratico di funzione anonima

Per chiarire meglio quanto esposto fino ad ora, verrà presentato di seguito un esempio pratico relativo all’utilizzo delle funzioni anonime, esso riguarda la realizzazione di una piccola applicazione in grado di contare e quindi sommare le occorrenze dei caratteri alfabetici che costituiscono i valori di un determinato vettore:

<?php
// definizione dell'array
$allenatori_inter = array('mancini', 'mourinho', 'benitez' , 'leonardo', 'gasperini', 'ranieri');
// applicazione del callback agli elementi dell'array
$allenatori_inter = array_map(function($valore){
// conversione delle stringhe in array
$caratteri = str_split($valore);
// conteggio dei caratteri
$conteggio  = array_count_values($caratteri);
// valore di ritorno
return $conteggio;
}, $allenatori_inter);
// somma dei caratteri presenti nei valori dell’array
$allenatori_inter = array_reduce($allenatori_inter, function($valore_singolo, $valore) {
    // ciclo d'iterazione delle sommatorie
    foreach ($valore as $carattere => $addendo) {
	// controllo sui valori non definiti
        if (!isset($valore_singolo[$carattere])) {
            $valore_singolo[$carattere] = 0;
        }
	// creazione dell'array contenente i risultati
        $valore_singolo[$carattere] += $addendo;
    }
// valore di ritorno
    return $valore_singolo;
});
// ordinamento dei valori in ordine decrescente
arsort($allenatori_inter);
// stampa del contenuto
foreach($allenatori_inter as $lettera=>$somma)
{
echo $lettera . " " . $somma."<br />n";
}
?>

Nel dettaglio, l'applicazione d'esempio consta dei seguenti passaggi:

  • viene definito un array avente come valori delle stringhe alfabetiche e ordinamento predefinito con indice numerico crescente a partire da 0;
  • viene introdotta la funzione array_map() che applica il callback agli elementi dell'array precedentemente definito, essa accetta come parametro una funzione anonima a cui a sua volta viene passata una variabile come argomento (array_map(function($valore){..);
  • str_split() ha quindi il compito di convertire le stringhe presenti nell'array in dei vettori che potranno essere conteggiati tramite la funzione array_count_values(), il risultato del conteggio sarà il primo valore di ritorno;
  • ritorna in gioco una funzione anonima tramite array_reduce(), quest'ultima ha infatti il compito di applicare iterativamente la funzione function() a tutti gli elementi che compongono un array, il risultato di questa operazione è quindi la riduzione del vettore in un singolo valore attraverso callback;
  • a questo punto, un ciclo foreach con il quale iterare l'array consentirà di sommare le occorrenze dei caratteri che compongono i valori del vettore originariamente definito, si ottiene così un secondo valore di ritorno che è poi l'array risultante dalle sommatorie eseguite tramite il ciclo;
  • si ha ora un array che ha come chiavi i singoli caratteri alfabetici rilevati dall'applicazione e come valori il numero delle loro occorrenze, la funzione arsort() consentirà di ordinare gli elementi del vettore in senso decrescente mantenendo le associazioni degli indici, basterà quindi un ciclo foreach per procedere con la stampa a video di tutte le coppie chiave=>valore.

Le chiusure

Le chiusure (closures) sono delle funzioni anonime che operano in riferimento al contesto corrente, un semplice esempio relativo al loro utilizzo potrebbe essere il seguente:

<?php
// definizione della chiusura
$funzione = function($var_a, $var_b) {
// valore di ritorno
return $var_a * $var_b;
};
// passaggio di parametri alla chiusura
$risultato = $funzione(10, 20);
// stampa a video del risultato
echo $risultato;
?>

Come è semplice notare, anche in questo caso non è stato associato alcun nome alla funzione definita; le closures di PHP permettono l'utilizzo della parola chiave use(), il suo scopo è quello di importare delle variabili, definite esternamente, all'interno della funzione anonima; in questo modo si evita il ricorso alla direttiva “global”, sarebbe infatti da considerarsi come una cattiva pratica il dichiarare come globale una variabile locale ampliandone lo scope.

Un semplice esempio riguardante l’impiego di use() potrebbe essere il seguente:

<?php
// definizione della classe
class EsempioDiClosure {
  // definizione dell'array da popolare
  public $allenatori_inter = array();
  // metodo per il popolamento dell'array
  public function setAllenatori_inter($allenatori_inter) {
    $this->allenatori_inter = $allenatori_inter;
  }
  // funzione per la sostituzione e la stampa a video
  public function a_capO($a_capo) {
  // variabili esterne
  $cerca = 'a';
  $sostituisci = '';
  // chiamata alle variabili esterne
  $closure = function ($testo) use ($cerca, $sostituisci, $a_capo) {
  	// sostituzione
  	$testo_risultante = str_replace($cerca, $sostituisci, $testo);
	// stampa a video
    echo ucfirst($testo_risultante) . $a_capo;
  };
  // applicazione della closure ad ogni elemento dell'array
  array_walk($this->allenatori_inter, $closure);
  }
}
#### utilizzo della classe
// istanza della classe
$istanza = new EsempioDiClosure;
// popolamento dell'array
$istanza->setAllenatori_inter(array('mancini', 'mourinho', 'benitez', 'leonardo', 'gasperini', 'ranieri'));
// chiamata al metodo della closure
$istanza->a_capO('<br />');
?>

La semplice applicazione presentata svolge il compito di generare un array, eliminare dai valori presenti un determinato carattere alfabetico (in questo caso la “a”) e di stampare a video le stringhe risultanti dalla sostituzione in modo che vengano presentate con iniziale maiuscola e che siano disposte una per riga.

Si noti come nella closure vengano richiamate tramite use() due variabili definite esternamente ad essa ($cerca e $sostituisci) nonché il metodo stesso in cui viene definita la closure, ciò esemplifica il concetto che vuole le chiusure in grado di utilizzare il contesto in cui sono inserite.

Attraverso l’utilizzo del magic method _invoke, lo sviluppatore avrà in qualsiasi momento la possibilità di convertire una classe in una chiusura:

<?php
// definizione della classe
class DaClasseAchiusura {
  // conversione in chiusura
  public function __invoke() {
  // output
  for ($x = 1; $x <= 10; ++$x) {
  $risultato = 5 * $x;
  echo '5 * ' .  $x . ' = '. $risultato .'<br />';
   }
  }
}
// istanza della classe
$DaClasseAchiusura = new DaClasseAchiusura();
// stampa a video
$DaClasseAchiusura();
?>

Così come le closures, anche il metodo __invoke(), concepito per consentire la chiamata di un oggetto come funzione, è disponibile in PHP a partire dalla versione 5.3.

Conclusioni

In questa trattazione è stato introdotto l'argomento relativo alle funzioni anonime; queste, disponibili in PHP a partire dalla versione 5.3, sono in pratica delle funzioni che possono essere impiegate come parametri per altre funzioni e risultano particolarmente utili nel caso in cui si abbia la necessità di utilizzare numerose funzioni per svolgere operazioni specifiche, senza doverle obbligatoriamente definire associando ad esse un nom


Ti consigliamo anche