Nueva pregunta

Pregunta:

Fecha: 25-08-2015 06:24:26 (En Español)

[APORTE] CLOSURE / Funciones Anónimas en PHP[Resuelta]

Hace un tiempo que estoy pensando en funciones anónimas en PHP, aquí mi aporte.

Closure en PHP es una clase incorporada a partir de PHP 5.3.0 (bienvenida sea) que permite representar funciones anónimas en PHP.

Código de Closure:
 Closure {
/* Métodos */
private __construct ( void )
public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] )
public Closure bindTo ( object $newthis [, mixed $newscope = "static" ] )
public mixed call ( object $newthis [, mixed $... ] )
}


* Closure::__construct — Constructor que anula la instanciación
* Closure::bind — Duplicar una clausura con un objeto vinculado y ámbito de clase especificados
* Closure::bindTo — Duplicar la clausura con un objeto vinculado y ámbito de clase nuevos
* Closure::call — Vincula y llama a la clausura

Como su constructor es privado no podremos crear objetos con "new", aunque sí podrá hacerse por medio de métodos indirectos, como en el siguiente ejemplo "asignando una función a una variable", aquí el código:


<?php
$variableFuncionSaludar=function($nombre){
    return "Hola $nombre";
};

echo $variableFuncionSaludar('Fernando');

?>


Vemos que el var_dump() de la variable "$variableFuncionSaludar" nos devuelve "object(Closure)". Por otro lado también podriamos preguntar si su contenido es o no una instancia del tipo Closure:

<?php
var_dump($variableFuncionSaludar);

if($variableFuncionSaludar instanceof Closure){
    echo 'la variable "$variableFuncionSaludar" contiene un objeto del tipo "Closure"';
}else{
    echo 'la variable "$variableFuncionSaludar" NO CONTIENE un objeto del tipo "Closure"';
}
?>


No consfundir el concepto de "Funciones Anónimas" con "Funciones Variables", donde una variable almacena un string que se corresponde con el nombre de una función previamente declarada, veamoslo con código que siempre es más claro:

<?php
function saludar($nombre){
    return "Hola $nombre";
}

$variableX = 'saludar';

echo $variableX('Fernando');
?>


El comportamiento es similar, pero aquí la "$variableX" no es un objeto del tipo "Closure", sino un "string" con un largo de 7 caracteres (length=7).

Veamoslo con código:
<?php
var_dump($variableX);

if($variableX instanceof Closure){
    echo 'la variable "$variableX" contiene un objeto del tipo "Closure"';
}else{
    echo 'la variable "$variableX" NO CONTIENE un objeto del tipo "Closure"';
}
?>


La diferencia más importante es que con funciones anónimas no se requiere tener la función previamente declarada "en tiempo de desarrollo", sino que se puede construir y/o obtener desde una base de datos "en tiempo de ejecución" (pequeño detalle que hace la diferencia clave).

Espero que mi aporte les sea de ayuda. Me gustaría leer sus comentarios al respecto, si ya lo estan utilizando, etc.

Saludos!
Etiquetas: Aporte - PHP - PHP Avanzado Votos: 3 - Respuestas: 2 - Vistas: 25 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 26-08-2015 06:10:54 Un usuario de Facebook me hizo este comentario "...pero las funciones anonimas son posiblemente utiles... no se extiende la clase y le metes un metodo mas en vez de una funcion anonima, es mas practico no?"
    Salvando la falta de acentos (entendibles en Facebook) me dejo pensando en la forma de "agregar un método a una clase en tiempo de ejecución" lo que me llevo a esta solución con funciones anónimas, pero ojo, no es un método, sino una variable que contiene un Closure y una sobreescritura el método __call(), veamos el código:

    <?php
    class Persona {
        public function __call($method, $arguments) {
            return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
        }
    }
    
    $objetoPersona = new Persona();
    $objetoPersona->saludar = function($nombre) {
        return "Hola $nombre";
    };
    
    //es una variable 
    echo $objetoPersona->saludar('Fernando');
    
    echo '<br/>';
    
    if(method_exists($objetoPersona, 'saludar')){
        echo 'Existe el método "saludar" en el objeto contenido en la variable "$objetoPersona"';
    }else{
        echo 'No existe el método "saludar" en el objeto contenido en la variable "$objetoPersona"';
    }
    
    
    //en realidad "saludar" no es un método, sino una variable que contiene una función anonima (un objeto Closure)
    echo '<pre>';
    var_dump($objetoPersona->saludar);
    echo '</pre>';
    ?>



    Ojo con este detalle: la clase Closure existe desde 5.3, pero el método bind() desde 5.4, por lo que en una versión 5.3.8 (por ejemplo) nos va a dar el error fatal: "Fatal error: Call to undefined method Closure::bind()"

    Se requiere PHP 5.4 o superior (yo estoy probando con 5.6).

    Ahora bien, si usas 5.3 también podes obviar el uso del método bind(), cambiando el método __call() por el siguiente:
        //para versiones anteriores a php 5.4
        public function __call($method, $args) {
            if (isset($this->$method)) {
                $func = $this->$method;
                return call_user_func_array($func, $args);
            }
        }


    Otra forma un poco mas elegante para incorporar métodos a una clase en tiempo de ejecución es implementar el "patrón Decorator", a ver si alguien da un ejemplo de esto (como un nuevo aporte y enlazando aquí con un link).

    Espero sus comentarios.

    Saludos!
      Votos: 2 - Link respuesta
     
  • Fecha: 30-08-2015 02:31:44 Nada más no se vayan con la finta por el nombre que le dieron a la clase que maneja las funciones anónimas puede confundir.
    PHP con esta clase soporta 3 cosas:
    1. Funciones anónimas.
    2. Lambdas.
    3. Closures (forzando el scope con use :P).
    No es tan diferente de las mismas en javascript, sólo tengan cuidado con las referencias en los closures. La única limitante que yo detecto es que las funciones anónimas en PHP no son auto invocables pero hasta ahora no he tenido necesidad de hacerlo en PHP :)
      Votos: 2 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión
 
frjcbbae garagebible.com