PHP call_user_func vs juste appeler la fonction

90

Je suis sûr qu'il y a une explication très simple à cela. Quelle est la différence entre ceci:

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

... et ceci (et quels sont les avantages?):

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

Réponses:

87

Utilisez toujours le nom réel de la fonction lorsque vous le connaissez.

call_user_func est pour appeler des fonctions dont vous ne connaissez pas le nom à l'avance, mais c'est beaucoup moins efficace car le programme doit rechercher la fonction à l'exécution.

Kai
la source
Merci Kai. call_user_func s'est avéré être exactement ce dont j'avais besoin.
geai
44
call_user_funcn'est pas nécessairement nécessaire. Vous pouvez toujours appeler une fonction en utilisant des fonctions variables: $some_func(). call_user_func_arrayest celui qui est vraiment utile.
Ionuț G. Stan
23
php a toujours besoin de "rechercher la fonction au moment de l'exécution"
VolkerK
2
@Pacerier Incorrect. Les fonctions anonymes sont toujours dans les variables, ie $func = function(){};. Tout paramètre possible de call_user_func doit être appelable, ce qui signifie qu'il contient suffisamment de données pour y accéder directement, que ce soit $func(), ou $obj->{$func}(), ou autre.
Benubird
2
Le "moins efficace" est en fait très peu, surtout depuis php7, c'est environ quelques ms / million d'appels: github.com/fab2s/call_user_func
fab2s
32

Bien que vous puissiez appeler les noms de fonctions variables de cette façon:

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

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

il y a des cas où vous ne savez pas combien d'arguments vous transmettez. Considérer ce qui suit:

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

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

C'est également pratique pour appeler des méthodes statiques et objet, respectivement:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);
Lucas Oman
la source
8
Je sais que c'est très vieux, mais je n'ai pas pu trouver d'articles ailleurs. Est-il plus avantageux d'utiliser call_user_func ('customFunction') comme associé à $ variableFunction ()? Quelles sont les différences? Merci!
David Hobs
15

l' call_user_funcoption est là pour que vous puissiez faire des choses comme:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

où la dynamicFunctionNamechaîne pourrait être plus excitante et générée au moment de l'exécution. Vous ne devriez pas utiliser call_user_func sauf si vous devez le faire, car il est plus lent.

Brian Schroth
la source
1
Il semble que vous puissiez utiliser une fonction variable dans ce scénario.
Anthony Rutledge
6

J'imagine que c'est utile pour appeler une fonction dont vous ne connaissez pas le nom à l'avance ... Quelque chose comme:

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

call_user_func($func, 'stuff');
pivot
la source
5
Nan. Nous pouvons encore faire$func('stuff');
ankush981
1
Oui, mais la différence est que l'utilisation d'une variable produira une erreur PHP fatale par rapport à un avertissement PHP si call_user_func est utilisé.
Robert Brisita le
Cela n'a pas annulé la valeur des fonctions variables call_user_func()dans ce scénario.
Anthony Rutledge
4

Avec PHP 7, vous pouvez utiliser partout la meilleure syntaxe de fonction variable. Il fonctionne avec des fonctions statiques / d'instance et peut prendre un tableau de paramètres. Plus d'informations sur https://trowski.com/2015/06/20/php-callable-paradox

$ret = $callable(...$params);
mils
la source
3

Il n'y a aucun avantage à appeler la fonction comme ça parce que je pense que c'était principalement utilisé pour appeler la fonction "utilisateur" (comme le plugin) parce que l'édition du fichier core n'est pas une bonne option. voici un exemple sale utilisé par 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
?>

production

hello world my name is Tasikmalaya
uingtea
la source
0

dans votre premier exemple, vous utilisez le nom de la fonction qui est une chaîne. il peut venir de l'extérieur ou être déterminé à la volée. c'est-à-dire que vous ne savez pas quelle fonction devra être exécutée au moment de la création du code.

SilentGhost
la source
-1

Lors de l'utilisation d'espaces de noms, call_user_func () est le seul moyen d'exécuter une fonction dont vous ne connaissez pas le nom au préalable, par exemple:

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

Si toutes vos fonctions étaient dans le même espace de noms, alors ce ne serait pas un tel problème, car vous pourriez utiliser quelque chose comme ceci:

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

Edit: Après @Jannis disant que je me trompe, j'ai fait un peu plus de tests et je n'ai pas eu beaucoup de chance:

<?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()'
}

Vous pouvez voir les résultats de sortie ici: https://3v4l.org/iBERh il semble que la deuxième méthode fonctionne à partir de PHP 7, mais pas de PHP 5.6.

ThomasRedstone
la source
. pour ne pas être vrai. $ fn = '\ Foo \ Bar \ getCurrency'; $ fn ();
Jan Sverre
Salut @Jannis, je ne trouve pas que c'est vrai, peut-être que vous pouvez voir où je me trompe, j'ai ajouté un exemple plus détaillé à ma réponse.
ThomasRedstone
@ThomasRedstone aviez-vous besoin de ces fonctions au préalable? php ne charge pas automatiquement les fonctions à partir d'autres fichiers. Qu'y a-t-il aussi de petites et grandes lettres dans les espaces de noms. Bar est-il une classe? alors c'est un autre cas d'utilisation.
przemo_li
salut @przemo_li, ceci est un seul fichier (tout dans l'espace de noms), je ne sais pas ce qui s'est passé avec le nom de l'espace de noms, pour ma défense, j'ai écrit la réponse il y a 4 ans, j'ai mis à jour l'espace de noms et ajouté dans une note à propos de PHP 7, avec un lien pour voir la sortie réelle. Je ne sais toujours pas comment jansverre l'a fait fonctionner, PHP 7 n'est entré en alpha que le 11 juin 2015
ThomasRedstone