PHP call_user_func vs. nur Funktion aufrufen

90

Ich bin sicher, dass es dafür eine sehr einfache Erklärung gibt. Was ist der Unterschied zwischen diesen:

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

... und das (und was sind die Vorteile?):

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

Antworten:

87

Verwenden Sie immer den tatsächlichen Funktionsnamen, wenn Sie ihn kennen.

call_user_func dient zum Aufrufen von Funktionen, deren Namen Sie nicht im Voraus kennen, die jedoch viel weniger effizient sind, da das Programm die Funktion zur Laufzeit nachschlagen muss.

Kai
quelle
Danke Kai. call_user_func erwies sich als genau das, was ich brauchte.
Jay
44
call_user_funcwird nicht unbedingt benötigt. Sie können eine Funktion jederzeit mit variablen Funktionen aufrufen : $some_func(). call_user_func_arrayist derjenige, der wirklich nützlich ist.
Ionuț G. Stan
22
PHP muss immer "die Funktion zur Laufzeit
nachschlagen
2
@ Pacerier Falsch. Anonyme Funktionen sind immer noch in Variablen, dh $func = function(){};. Jeder möglicher Parameter call_user_func hat aufrufbar zu sein, was bedeutet , dass es genügend Daten für den Zugriff enthält es direkt, ob das $func(), oder $obj->{$func}(), oder was auch immer.
Benubird
1
Die "weniger effiziente" ist eigentlich sehr wenig, besonders seit PHP7, es geht um wenige ms / Million Anrufe: github.com/fab2s/call_user_func
fab2s
32

Obwohl Sie variable Funktionsnamen folgendermaßen aufrufen können:

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

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

Es gibt Fälle, in denen Sie nicht wissen, wie viele Argumente Sie übergeben. Folgendes berücksichtigen:

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

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

Es ist auch praktisch, um statische bzw. Objektmethoden aufzurufen:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);
Lucas Oman
quelle
8
Ich weiß, dass dies uralt ist, konnte aber anderswo keine Artikel finden. Ist es vorteilhafter, call_user_func ('customFunction') als $ variableFunction () zu verwenden? Was sind die Unterschiede? Vielen Dank!
David Hobs
15

Die call_user_funcOption ist da, damit Sie Dinge tun können wie:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

wo die dynamicFunctionNameZeichenfolge aufregender sein und zur Laufzeit generiert werden könnte. Sie sollten call_user_func nicht verwenden, es sei denn, Sie müssen, weil es langsamer ist.

Brian Schroth
quelle
1
Es scheint, als könnten Sie in diesem Szenario eine variable Funktion verwenden.
Anthony Rutledge
6

Ich stelle mir vor, es ist nützlich, um eine Funktion aufzurufen, deren Namen Sie nicht im Voraus kennen ... So etwas wie:

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

call_user_func($func, 'stuff');
schwenkbar
quelle
5
Nee. Wir können es immer noch tun$func('stuff');
ankush981
1
Ja, aber der Unterschied bei der Verwendung einer Variablen führt zu einem schwerwiegenden PHP-Fehler gegenüber einer PHP-Warnung, wenn call_user_func verwendet wird.
Robert Brisita
Dies hat den Wert variabler Funktionen call_user_func()in diesem Szenario nicht negiert .
Anthony Rutledge
4

Mit PHP 7 können Sie überall die schönere Syntax mit variablen Funktionen verwenden. Es funktioniert mit statischen / Instanzfunktionen und kann eine Reihe von Parametern annehmen. Weitere Informationen unter https://trowski.com/2015/06/20/php-callable-paradox

$ret = $callable(...$params);
mils
quelle
3

Es gibt keine Vorteile, wenn man die Funktion so aufruft, weil ich denke, dass sie hauptsächlich zum Aufrufen der "Benutzer" -Funktion (wie das Plugin) verwendet wird, da das Bearbeiten der Kerndatei keine gute Option ist. Hier sind schmutzige Beispiele, die von Wordpress verwendet werden

<?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
?>

Ausgabe

hello world my name is Tasikmalaya
uingtea
quelle
0

In Ihrem ersten Beispiel verwenden Sie den Funktionsnamen, bei dem es sich um eine Zeichenfolge handelt. es kann von außen kommen oder im laufenden Betrieb bestimmt werden. Das heißt, Sie wissen nicht, welche Funktion zum Zeitpunkt der Codeerstellung ausgeführt werden muss.

SilentGhost
quelle
-1

Wenn Sie Namespaces verwenden, ist call_user_func () die einzige Möglichkeit, eine Funktion auszuführen, deren Namen Sie vorher nicht kennen, zum Beispiel:

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

Wenn sich alle Ihre Funktionen im selben Namespace befinden würden, wäre dies kein Problem, da Sie Folgendes verwenden könnten:

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

Edit: Nachdem @Jannis gesagt hat, dass ich falsch liege, habe ich ein bisschen mehr getestet und hatte nicht viel Glück:

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

Sie können die Ausgabeergebnisse hier sehen: https://3v4l.org/iBERh Es scheint, dass die zweite Methode ab PHP 7 funktioniert, nicht jedoch PHP 5.6.

Thomas Redstone
quelle
. für nicht wahr sein. $ fn = '\ Foo \ Bar \ getCurrency'; $ fn ();
Jan Sverre
Hallo @Jannis, ich finde das nicht wahr. Vielleicht kannst du sehen, wo ich falsch liege. Ich habe meiner Antwort ein detaillierteres Beispiel hinzugefügt.
Thomas Redstone
@ThomasRedstone haben Sie diese Funktionen vorher benötigt? PHP laden nicht automatisch Funktionen aus anderen Dateien. Auch was ist mit diesen kleinen gegen großen Buchstaben in Namespaces. Ist Bar eine Klasse? dann ist das ein weiterer Anwendungsfall.
przemo_li
hi @przemo_li, dies ist eine einzelne Datei (alle innerhalb des Namespace), nicht sicher, was mit dem Namespace-Namen passiert ist. Zu meiner Verteidigung habe ich die Antwort vor 4 Jahren geschrieben, den Namespace aktualisiert und einen Hinweis hinzugefügt PHP 7, mit einem Link, um die tatsächliche Ausgabe zu sehen. Ich weiß immer noch nicht, wie jansverre es funktioniert hat, PHP 7 hat Alpha erst am 11. Juni 2015
eingegeben