PHP call_user_func vs solo función de llamada

90

Estoy seguro de que hay una explicación muy sencilla para esto. ¿Cuál es la diferencia entre esto?

function barber($type){
    echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");

... y esto (¿y cuáles son los beneficios?):

function barber($type){
    echo "You wanted a $type haircut, no problem\n";
}
barber('mushroom');
barber('shave');
arrendajo
fuente

Respuestas:

87

Utilice siempre el nombre real de la función cuando lo sepa.

call_user_func es para llamar a funciones cuyo nombre no conoce de antemano, pero es mucho menos eficiente ya que el programa tiene que buscar la función en tiempo de ejecución.

Kai
fuente
Gracias Kai. call_user_func resultó ser exactamente lo que necesitaba.
jay
44
call_user_funcno es necesariamente necesario. Siempre se puede llamar a una función mediante el uso de funciones variables: $some_func(). call_user_func_arrayes el que es realmente útil.
Ionuț G. Stan
23
php siempre necesita "buscar la función en tiempo de ejecución"
VolkerK
2
@Pacerier Incorrecto. Las funciones anónimas todavía están en variables, es decir $func = function(){};. Cualquier posible parámetro para call_user_func tiene que ser exigible, lo que significa que contiene datos suficientes para acceder a ella directamente, ya sea $func(), o $obj->{$func}(), o lo que sea.
Benubird
2
El "menos eficiente" es en realidad muy poco, especialmente desde php7, se trata de unos pocos ms / millón de llamadas: github.com/fab2s/call_user_func
fab2s
32

Aunque puede llamar a los nombres de funciones variables de esta manera:

function printIt($str) { print($str); }

$funcname = 'printIt';
$funcname('Hello world!');

hay casos en los que no sabe cuántos argumentos está pasando. Considera lo siguiente:

function someFunc() {
  $args = func_get_args();
  // do something
}

call_user_func_array('someFunc',array('one','two','three'));

También es útil para llamar a métodos estáticos y de objetos, respectivamente:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);
Lucas Omán
fuente
8
Sé que esto es muy antiguo, pero no pude encontrar artículos en otros lugares. ¿Es más ventajoso usar call_user_func ('customFunction') en lugar de $ variableFunction ()? ¿Cuáles son las diferencias? ¡Gracias!
David Hobs
15

la call_user_funcopción está ahí para que pueda hacer cosas como:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

donde la dynamicFunctionNamecadena podría ser más emocionante y generada en tiempo de ejecución. No debe usar call_user_func a menos que sea necesario, porque es más lento.

Brian Schroth
fuente
1
Parece que podría usar una función variable en este escenario.
Anthony Rutledge
6

Imagino que es útil para llamar a una función de la que no conoces el nombre de antemano ... Algo como:

switch($value):
{
  case 7:
  $func = 'run';
  break;
  default:
  $func = 'stop';
  break;
}

call_user_func($func, 'stuff');
esencial
fuente
5
No Todavía podemos hacer$func('stuff');
ankush981
1
Sí, pero la diferencia es que el uso de una variable producirá un error fatal de PHP frente a una advertencia de PHP si se usa call_user_func.
Robert Brisita
Esto no ha negado el valor de las funciones variables call_user_func()en este escenario.
Anthony Rutledge
4

Con PHP 7 puede usar la sintaxis de función variable más agradable en todas partes. Funciona con funciones estáticas / de instancia y puede tomar una serie de parámetros. Más información en https://trowski.com/2015/06/20/php-callable-paradox

$ret = $callable(...$params);
milésimas de pulgada
fuente
3

No hay beneficios para llamar a la función de esa manera porque creo que se usa principalmente para llamar a la función "usuario" (como un complemento) porque editar el archivo central no es una buena opción. aquí hay un ejemplo sucio utilizado por Wordpress

<?php
/* 
* my_plugin.php
*/

function myLocation($content){
  return str_replace('@', 'world', $content);
}

function myName($content){
  return $content."Tasikmalaya";
}

add_filter('the_content', 'myLocation');
add_filter('the_content', 'myName');

?>

...

<?php
/*
* core.php
* read only
*/

$content = "hello @ my name is ";
$listFunc = array();

// store user function to array (in my_plugin.php)
function add_filter($fName, $funct)
{
  $listFunc[$fName]= $funct;
}

// execute list user defined function
function apply_filter($funct, $content)
{
  global $listFunc;

  if(isset($listFunc))
  {
    foreach($listFunc as $key => $value)
    {
      if($key == $funct)
      {
        $content = call_user_func($listFunc[$key], $content);
      }
    }
  }
  return $content;
}

function the_content()
{
  $content = apply_filter('the_content', $content);
  echo $content;
}

?>

....

<?php
require_once("core.php");
require_once("my_plugin.php");

the_content(); // hello world my name is Tasikmalaya
?>

salida

hello world my name is Tasikmalaya
uingtea
fuente
0

en su primer ejemplo, está usando un nombre de función que es una cadena. puede provenir del exterior o determinarse sobre la marcha. es decir, no sabe qué función deberá ejecutarse en el momento de la creación del código.

SilentGhost
fuente
-1

Cuando se utilizan espacios de nombres, call_user_func () es la única forma de ejecutar una función que no conoce el nombre de antemano, por ejemplo:

$function = '\Utilities\SearchTools::getCurrency';
call_user_func($function,'USA');

Si todas sus funciones estuvieran en el mismo espacio de nombres, entonces no sería un problema, ya que podría usar algo como esto:

$function = 'getCurrency';
$function('USA');

Editar: Siguiendo a @Jannis diciendo que estoy equivocado, hice un poco más de pruebas y no tuve mucha suerte:

<?php
namespace Foo {

    class Bar {
        public static function getBar() {
            return 'Bar';
        }
    }
    echo "<h1>Bar: ".\Foo\Bar::getBar()."</h1>";
    // outputs 'Bar: Bar'
    $function = '\Foo\Bar::getBar';
    echo "<h1>Bar: ".$function()."</h1>";
    // outputs 'Fatal error: Call to undefined function \Foo\Bar::getBar()'
    $function = '\Foo\Bar\getBar';
    echo "<h1>Bar: ".$function()."</h1>";
    // outputs 'Fatal error: Call to undefined function \foo\Bar\getBar()'
}

Puede ver los resultados de salida aquí: https://3v4l.org/iBERh parece que el segundo método funciona para PHP 7 en adelante, pero no PHP 5.6.

ThomasRedstone
fuente
. por no ser verdad. $ fn = '\ Foo \ Bar \ getCurrency'; $ fn ();
Jan Sverre
Hola @Jannis, no encuentro que eso sea cierto, tal vez puedas ver dónde me equivoco, agregué un ejemplo más detallado a mi respuesta.
ThomasRedstone
@ThomasRedstone, ¿requirió esas funciones de antemano? php no carga automáticamente funciones de otros archivos. Además, ¿qué pasa con las letras pequeñas y grandes en los espacios de nombres? ¿Bar es una clase? entonces ese es otro caso de uso.
przemo_li
hola @przemo_li, este es un solo archivo (todo dentro del espacio de nombres), no estoy seguro de qué sucedió con el nombre del espacio de nombres, en mi defensa, escribí la respuesta hace 4 años, actualicé el espacio de nombres y agregué una nota sobre PHP 7, con un enlace para ver la salida real. Todavía no sé cómo jansverre lo hizo funcionar, PHP 7 no entró en alfa hasta el 11 de junio de 2015
ThomasRedstone