El PHP manual for anonymous functions (es decir, los cierres) establece que:Testing para un cierre PHP sin hacer referencia a la clase interna Closure
funciones anónimas se implementan actualmente utilizando la clase de cierre. Este es un detalle de implementación y no se debe confiar en.
(El énfasis es mío)
¿Es posible probar una variable, de tal manera que la prueba devuelve verdadero si la variable es un cierre, sin hacer referencia a la clase de cierre?
En otras palabras, ¿cómo puedo volver a escribir el siguiente ejemplo que va a haber un error al $bar
es otra cosa que una función anónima:
function foo(Closure $bar) { $bar(); }
EDIT: En base a las respuestas recibidas, aquí es una prueba de ejemplo .
Notas:
- Parece que no hay manera de diferenciar entre Functors y cierres, y que la prueba es probablemente tan 'aplicación específica' como el uso de la clase de cierre.
- El método (aparentemente obvio)
ReflectionFunction::isClosure()
parece ser casi inútil: en el momento en que ha realizado las comprobaciones necesarias para asegurarse de que ReflectionFunction pueda realmente crearse una instancia (no puede tomar una Clase a excepción de un Cierre), usted eliminé todas las demás opciones. - En 5.3.0, ReflectionClass ($ closure) -> hasMethod ('__ invoke') devolvió false, por lo que podría usarse como una prueba contra Functors, sin embargo (me dicen) esto ha cambiado desde entonces. Esto resalta la fragilidad de la solución también.
- Seguimiento de Gordon - A partir de PHP 5.4 se puede confiar en Cierre de ser un Cierre: php.net/manual/en/class.closure.php
Código: caso
/**
* Return true if and only if the passed argument is a Closure.
*/
function testClosure($a) {
// Must be Callback, Labmda, Functor or Closure:
if(!is_callable($a)) return false;
// Elminate Callbacks & Lambdas
if(!is_object($a)) return false;
// Eliminate Functors
//$r = new ReflectionFunction($a); <-- fails if $a is a Functor
//if($r->isClosure()) return true;
return false;
}
prueba:
//////////// TEST CASE /////////////
class CallBackClass {
function callBackFunc() {
}
}
class Functor {
function __invoke() {
}
}
$functor = new Functor();
$lambda = create_function('', '');
$callback = array('CallBackClass', 'callBackFunc');
$array = array();
$object = new stdClass();
$closure = function() { ; };
echo "Is it a closure? \n";
echo "Closure: " . (testClosure($closure) ? "yes" : "no") . "\n";
echo "Null: " . (testClosure(null) ? "yes" : "no") . "\n";
echo "Array: " . (testClosure($array) ? "yes" : "no") . "\n";
echo "Callback: " . (testClosure($callback) ? "yes" : "no") . "\n";
echo "Labmda: " .(testClosure($lambda) ? "yes" : "no") . "\n";
echo "Invoked Class: " . (testClosure($functor) ? "yes" : "no") . "\n";
echo "StdObj: " . (testClosure($object) ? "yes" : "no") . "\n";
-
¿Qué pasa con funciones creadas usando 'create_function', funciones anónimas del pobre hombre de delante de PHP 5.3? ¿Qué pasa con los objetos que pueden ser '__invoke()' d? – janmoesen
Estoy especialmente interesado en si puede realizar una prueba para un Cierre ("... devuelve verdadero solo si la variable es un Cierre ...") – Hamish
Mi pregunta para usted es por qué le gustaría distinguir entre un functor (o cualquier devolución de llamada en ese punto) y un cierre? En 5.3, no hay diferencia desde su punto de vista (ya que no puede vincular nada), entonces, ¿qué importa? Si pasa 'is_callable()', ¿por qué no es suficiente? – ircmaxell