Chiusure in PHP & # 8230; che cosa sono esattamente e quando avresti bisogno di usarli?

StackOverflow https://stackoverflow.com/questions/146737

  •  02-07-2019
  •  | 
  •  

Domanda

Quindi sto programmando in modo bello, aggiornato e orientato agli oggetti. Faccio regolarmente uso dei vari aspetti di OOP implementati da PHP, ma mi chiedo quando potrei aver bisogno di usare le chiusure. Qualche esperto là fuori che può far luce su quando sarebbe utile implementare le chiusure?

È stato utile?

Soluzione

PHP supporterà le chiusure in modo nativo in 5.3. Una chiusura è utile quando si desidera una funzione locale utilizzata solo per scopi specifici di piccole dimensioni. Le RFC per chiusure danno un buon esempio:

function replace_spaces ($text) {
    $replacement = function ($matches) {
        return str_replace ($matches[1], ' ', ' ').' ';
    };
    return preg_replace_callback ('/( +) /', $replacement, $text);
}

Ciò ti consente di definire la funzione sostituzione localmente all'interno di replace_spaces () , in modo che non sia:
1) ingombrando lo spazio dei nomi globale
2) Rendere le persone a tre anni di distanza si chiede perché esiste una funzione definita a livello globale che viene utilizzata solo all'interno di un'altra funzione

Mantiene le cose organizzate. Notare come la funzione stessa non abbia un nome, è semplicemente definita e assegnata come riferimento a $ sostituzione .

Ma ricorda, devi aspettare PHP 5.3 :)

Puoi anche accedere alle variabili al di fuori del suo ambito in una chiusura usando la parola chiave usa . Considera questo esempio.

// Set a multiplier  
 $multiplier = 3;

// Create a list of numbers  
 $numbers = array(1,2,3,4);

// Use array_walk to iterate  
 // through the list and multiply  
 array_walk($numbers, function($number) use($multiplier){  
 echo $number * $multiplier;  
 }); 

Una eccellente spiegazione è fornita qui Cosa sono lambda e chiusure php

Altri suggerimenti

Quando in futuro avrai bisogno di una funzione che esegua un'attività che hai deciso ora.

Ad esempio, se leggi un file di configurazione e uno dei parametri indica che hash_method per il tuo algoritmo è moltiplica anziché square , è possibile creare una chiusura che verrà utilizzata ovunque sia necessario hash qualcosa.

La chiusura può essere creata in (ad esempio) config_parser () ; crea una funzione chiamata do_hash_method () usando le variabili locali in config_parser () (dal file di configurazione). Ogni volta che viene chiamato do_hash_method () , ha accesso alle variabili nell'ambito locale di config_parser () anche se non viene chiamato in tale ambito.

Un buon esempio ipotetico:

function config_parser()
{
    // Do some code here
    // $hash_method is in config_parser() local scope
    $hash_method = 'multiply';

    if ($hashing_enabled)
    {
        function do_hash_method($var)
        {
            // $hash_method is from the parent's local scope
            if ($hash_method == 'multiply')
                return $var * $var;
            else
                return $var ^ $var;
        }
    }
}


function hashme($val)
{
    // do_hash_method still knows about $hash_method
    // even though it's not in the local scope anymore
    $val = do_hash_method($val)
}

Oltre ai dettagli tecnici, le chiusure sono un prerequisito fondamentale per uno stile di programmazione noto come programmazione orientata alle funzioni. Una chiusura è usata approssimativamente per la stessa cosa in cui usi un oggetto nella programmazione orientata agli oggetti; Associa i dati (variabili) insieme ad un po 'di codice (una funzione), che è quindi possibile passare da qualche altra parte. Pertanto, hanno un impatto sul modo in cui scrivi i programmi o, se non cambi il modo in cui scrivi i tuoi programmi, non hanno alcun impatto.

Nel contesto di PHP, sono un po 'strani, dal momento che PHP è già pesante sul paradigma di classe, orientato agli oggetti, nonché su quello procedurale più vecchio. Di solito, le lingue che hanno le chiusure hanno una portata lessicale completa. Per mantenere la retrocompatibilità, PHP non lo otterrà, quindi ciò significa che le chiusure saranno un po 'diverse qui, rispetto ad altre lingue. Penso che dobbiamo ancora vedere esattamente come verranno utilizzati.

Mi piace il contesto fornito dal post di troelskn. Quando voglio fare qualcosa come l'esempio di Dan Udey in PHP, uso il modello di strategia OO. Secondo me, questo è molto meglio dell'introduzione di una nuova funzione globale il cui comportamento è determinato in fase di esecuzione.

http://en.wikipedia.org/wiki/Strategy_pattern

Puoi anche chiamare funzioni e metodi usando una variabile che contiene il nome del metodo in PHP, il che è fantastico. quindi un'altra interpretazione dell'esempio di Dan sarebbe qualcosa del genere:

class ConfigurableEncoder{
        private $algorithm = 'multiply';  //default is multiply

        public function encode($x){
                return call_user_func(array($this,$this->algorithm),$x);
        }

        public function multiply($x){
                return $x * 5;
        }

        public function add($x){
                return $x + 5;
        }

        public function setAlgorithm($algName){
                switch(strtolower($algName)){
                        case 'add':
                                $this->algorithm = 'add';
                                break;
                        case 'multiply':        //fall through
                        default:                //default is multiply
                                $this->algorithm = 'multiply';
                                break;
                }
        }
}

$raw = 5;
$encoder = new ConfigurableEncoder();                           // set to multiply
echo "raw: $raw\n";                                             // 5
echo "multiply: " . $encoder->encode($raw) . "\n";              // 25
$encoder->setAlgorithm('add');
echo "add: " . $encoder->encode($raw) . "\n";                   // 10

ovviamente, se vuoi che sia disponibile ovunque, potresti semplicemente rendere tutto statico ...

Una chiusura è sostanzialmente una funzione per la quale si scrive la definizione in un contesto ma si esegue in un altro contesto. Javascript mi ??ha aiutato molto a comprenderli, perché sono utilizzati in JavaScript ovunque.

In PHP, sono meno efficaci rispetto a JavaScript, a causa delle differenze nella portata e nell'accessibilità del "globale". (o "esterne" variabili all'interno delle funzioni. Tuttavia, a partire da PHP 5.4, le chiusure possono accedere a $ questo oggetto quando eseguite all'interno di un oggetto, questo le rende molto più efficaci.

Questo è ciò che riguarda le chiusure, e dovrebbe essere sufficiente per capire cosa è scritto sopra.

Ciò significa che dovrebbe essere possibile scrivere una definizione di funzione da qualche parte e utilizzare $ this variabile all'interno della definizione di funzione, quindi assegnare la definizione di funzione a una variabile (altri hanno fornito esempi della sintassi), quindi passare questa variabile a un oggetto e chiamarlo nel contesto dell'oggetto, la funzione può quindi accedere e manipolare l'oggetto tramite $ this come se fosse solo un altro dei suoi metodi, quando in realtà non è definito nella definizione di classe di quell'oggetto, ma da qualche parte il resto.

Se non è molto chiaro, non preoccuparti, diventerà chiaro una volta che inizi a usarli.

Bascialmente, la chiusura sono le funzioni interne che hanno accesso alle variabili esterne e sono usate come una funzione di richiamata per una funzione anonima (funzioni che non hanno alcun nome).

 <?php
      $param='ironman';
      function sayhello(){
          $param='captain';
          $func=function () use ($param){
                $param='spiderman';
          };
       $func();
       echo  $param;
       }
      sayhello();
?>

//output captain

//and if we pass variable as a reference as(&$param) then output would be spider man;

Ecco alcuni esempi di chiusure in php

// Author: HishamDalal@gamil.com
// Publish on: 2017-08-28

class users
{
    private $users = null;
    private $i = 5;

    function __construct(){
        // Get users from database
        $this->users = array('a', 'b', 'c', 'd', 'e', 'f');
    }

    function displayUsers($callback){
        for($n=0; $n<=$this->i; $n++){
            echo  $callback($this->users[$n], $n);
        }
    }

    function showUsers($callback){
        return $callback($this->users);

    }

    function getUserByID($id, $callback){
        $user = isset($this->users[$id]) ? $this->users[$id] : null;
        return $callback($user);
    }

}

$u = new users();

$u->displayUsers(function($username, $userID){
    echo "$userID -> $username<br>";
});

$u->showUsers(function($users){
    foreach($users as $user){
        echo strtoupper($user).' ';
    }

});

$x = $u->getUserByID(2, function($user){

    return "<h1>$user</h1>";
});

echo ($x);

Output:

0 -> a
1 -> b
2 -> c
3 -> d
4 -> e
5 -> f

A B C D E F 

c
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top