2008-09-28 10 views

Respuesta

61

PHP apoyará cierres en forma nativa 5.3. Un cierre es bueno cuando desea una función local que solo se utiliza para un propósito pequeño y específico.El RFC for closures dan un buen ejemplo:

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

Esto le permite definir la función replacement localmente dentro replace_spaces(), por lo que no es:
1) desordenados en el espacio de nombres global
2) Hacer que la gente tres años después preguntarse por qué hay una función definida globalmente que solo se usa dentro de otra función

Mantiene las cosas organizadas. Observe cómo la función en sí no tiene nombre, simplemente se define y asigna como referencia al $replacement.

Pero recuerde, usted tiene que esperar para PHP 5.3 :)

+1

Esta es una explicación increíble. +1 –

+2

Disfruté de la explicación de ** por qué ** usaría cierres. La mayoría de las personas realmente no entienden eso. +1 –

+7

Esta es una explicación de las funciones anónimas, no una explicación de los cierres. Las funciones anónimas son, como usted dice, simplemente como funciones con nombre, excepto que no son globales. Los cierres, por otro lado, son funciones que contienen variables libres de ámbito léxico (declaradas con "uso"); es decir. pueden copiar y valores de referencia del ámbito en el que están declarados, incluso después de que todo lo demás haya sido recolectado. – Warbo

14

Cuando necesite una función en el futuro que realice una tarea que haya decidido ahora.

Por ejemplo, si se lee un archivo de configuración y uno de los parámetros que se dice que el hash_method para su algoritmo es multiply en lugar de square, puede crear un cierre que se utilizará siempre que se necesite para discutir algo.

El cierre se puede crear en (por ejemplo) config_parser(); crea una función llamada do_hash_method() usando variables locales a config_parser() (desde el archivo de configuración). Siempre que se llame al do_hash_method(), tiene acceso a variables en el ámbito local de config_parser() aunque no se llame en ese ámbito.

Un buen ejemplo es de esperar hipotética:

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) 
} 
+0

no puedo simplemente copiar y pegar este ejemplo y ejecutarlo. Preferí un ejemplo que simplemente puedo ejecutar. –

+14

-1 para el código que no funciona. – deceze

+1

Esta respuesta es pobre. Esta es una afirmación sin sentido: "Cuando necesitarás una función en el futuro que realice una tarea que hayas decidido ahora". – Puzbie

14

Aparte de los detalles técnicos, los cierres son un pre-requisito fundamental para un estilo de programación conocido como la programación orientada función. Un cierre se usa más o menos para lo mismo que se usa un objeto para la programación orientada a objetos; Vincula datos (variables) junto con algún código (una función), que luego puede pasar a otro lugar. Como tal, tienen un impacto en la forma en que escribes los programas o, si no cambias la forma en que escribes tus programas, no tienen ningún impacto.

En el contexto de PHP, son un poco raros, ya que PHP ya es pesado en el paradigma basado en clases, orientado a objetos, así como en el anterior procedural. Por lo general, los idiomas que tienen cierres tienen un alcance léxico completo. Para mantener la compatibilidad con versiones anteriores, PHP no va a obtener esto, por lo que los cierres van a ser un poco diferentes aquí que en otros idiomas. Creo que todavía tenemos que ver exactamente cómo se usarán.

8

Me gusta el contexto proporcionado por la publicación de troelskn. Cuando quiero hacer algo como el ejemplo de Dan Udey en PHP, uso el patrón de estrategia OO. En mi opinión, esto es mucho mejor que la introducción de una nueva función global cuyo comportamiento se determina en tiempo de ejecución.

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

También puede llamar a las funciones y los métodos que utilizan una variable que contiene el nombre del método en PHP, que es grande. así que otra toma en el ejemplo de Dan sería algo como esto:

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 

por supuesto, si usted quiere que sea disponible en todas partes, que sólo podría hacer que todo sea estática ...

1

Un cierre es básicamente una función para la que se escribe la definición en un contexto pero ejecuta en otro contexto. Javascript me ayudó mucho con la comprensión de estos, porque se utilizan en JavaScript en todo el lugar.

En PHP, son menos efectivos que en JavaScript, debido a las diferencias en el alcance y la accesibilidad de las variables "globales" (o "externas") desde dentro de las funciones. Sin embargo, comenzando con PHP 5.4, los cierres pueden acceder al $ este objeto cuando se ejecuta dentro de un objeto, esto los hace mucho más efectivos.

De esto se tratan los cierres, y debería ser suficiente para entender lo que está escrito anteriormente.

Esto significa que debería ser posible escribir una definición de función en alguna parte, usar $ esta variable dentro de la definición de función, asignar la definición de función a una variable (otros han dado ejemplos de la sintaxis), luego pasar esto variable a un objeto y lo llama en el contexto del objeto, la función puede acceder y manipular el objeto a través de $ this como si fuera uno más de sus métodos, cuando en realidad no está definido en la definición de clase de ese objeto, pero en algún otro lugar.

Si no está muy claro, entonces no se preocupe, se aclarará una vez que comience a usarlos.

+0

Honestamente, esto no está nada claro, ni siquiera para mí, el autor. Básicamente, digo: para conocer qué cierres se verifican en JavaScript, pero tenga en cuenta que el alcance variable es diferente entre JavaScript y PHP. – Rolf

0

Éstos son ejemplos de cierres en php

// Author: [email protected] 
// 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); 

Salida:

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

A B C D E F 

c 
Cuestiones relacionadas