php is_function () para determinar si una variable es una función

89

Estaba muy emocionado de leer sobre las funciones anónimas en php, que te permiten declarar una variable que funciona más fácilmente de lo que podrías hacer con create_function . Ahora me pregunto si tengo una función a la que se le pasa una variable, ¿cómo puedo verificarla para determinar si es una función? Todavía no hay una función is_function (), y cuando hago un var_dump de una variable que es una función:

$func = function(){
    echo 'asdf';
};
var_dump($func);

Entiendo esto:

object(Closure)#8 (0) { } 

¿Alguna idea sobre cómo comprobar si se trata de una función?

Jage
fuente

Respuestas:

142

Úselo is_callablepara determinar si una variable dada es una función. Por ejemplo:

$func = function()
{  
    echo 'asdf';  
};

if( is_callable( $func ) )
{
    // Will be true.
}
Jon Benedicto
fuente
10
is_callable () funcionará muy bien ya sea que esté pasando una función anónima, un nombre de función como una cadena o una matriz de devolución de llamada PHP válida. Si desea verificar específicamente solo funciones anónimas, entonces querrá algo como lo que dijo Gumbo: asegúrese de que el parámetro sea un objeto y asegúrese de que sea una instancia de Closure.
Lane
2
¿Qué pasa si quiero verificar si es un callack o una cuerda y hacer cosas diferentes por ellos? No quiero que un valor de cadena se tome accidentalmente como devolución de llamada.
Gherman
3
@German Solo verifique primero si is_string ($ func) y luego como segunda verificación con is_callable ($ func)
Heroselohim
4
El fragmento de código anterior me metió en problemas. Tenía la intención de una cadena con la etiqueta "Fecha" y luego se manejó como un cierre y se ejecutó. La forma correcta es si (($ variable instancia de cierre) && is_callable ($ variable)) {...}
Basil Musa
1
Por qué la instancia de cierre AND es invocable. ¿Cuándo no es invocable un cierre? No me sorprendería si hubiera un momento, pero tengo curiosidad por saber por qué necesitamos ambos controles.
Joel M
34

Puede utilizar function_existspara comprobar que existe una función con el nombre de pila. Y para combinar eso con funciones anónimas, intente esto:

function is_function($f) {
    return (is_string($f) && function_exists($f)) || (is_object($f) && ($f instanceof Closure));
}
Gumbo
fuente
¡Gracias por esto! Mi aplicación permite a los usuarios especificar su propia función hash o, alternativamente, proporcionar un argumento para hash (). Pero algunos de los algoritmos hash válidos también son incorporados de PHP y, por lo tanto, se pueden llamar ('md5', 'sha1', por ejemplo). is_object()¡y instanceof Closurees una forma mucho más sólida de comprobarlo!
njbair
Elimine las llamadas is_string y function_exists y esta es la función que desea usar para detectar funciones lambda. ¡Gracias!
jack
30

Si solo desea verificar si una variable es una función anónima y no una cadena o matriz invocable, use instanceof.

$func = function()
{  
    echo 'asdf';  
};

if($func instanceof Closure)
{
    // Will be true.
}

Las funciones anónimas (del tipo que se agregaron en PHP 5.3) son siempre instancias de la Closureclase, y cada instancia de la Closureclase es una función anónima.

Hay otro tipo de cosas en PHP que posiblemente podrían considerarse una función, y son los objetos que implementan el __invokemétodo mágico. Si desea incluirlos (sin dejar de excluir cadenas y matrices), use method_exists($func, '__invoke'). Esto todavía incluirá cierres, ya que los cierres se implementan __invokepara mantener la coherencia.

Brillante
fuente
8
Esto es particularmente útil, porque is_callable()intentará encontrar un método para llamar basado en una cadena o matriz pasada, que puede cargar clases automáticamente y puede que no sea el comportamiento que espera / requiere.
spikyjt
2
function is_function($f) {
    return is_callable($f) && !is_string($f);
}
Artemiy Stagnant Ice Alexeew
fuente
En el futuro, PHP podría cambiar gettype () de Object a Callable, como ya lo hacen otros lenguajes. Entonces, esta respuesta es probablemente la mejor manera de hacerlo. Pero esto se puede optimizar como: return! Is_string ($ f) &&! Is_array ($ f) && is_callable ($ f).
Alexandre T.
0

En php, los invocables válidos pueden ser funciones, nombre de funciones (cadenas) y matrices de las formas ['className', 'staticMethod']o [$object, 'method'], por lo tanto, para detectar solo las funciones necesitan excluir cadenas y matrices:

function isFunction($callable) {
    return $callable && !is_string($callable) && !is_array($callable) && is_callable($callable);
}
Andrey Izman
fuente