PHP call_user_func vs. solo chiamata di funzione


90

Sono sicuro che ci sia una spiegazione molto semplice per questo. Qual è la differenza tra questo:

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

... e questo (e quali sono i vantaggi?):

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

Risposte:


87

Usa sempre il nome effettivo della funzione quando lo conosci.

call_user_func serve per chiamare funzioni di cui non si conosce il nome in anticipo, ma è molto meno efficiente poiché il programma deve cercare la funzione in fase di esecuzione.


Grazie Kai. call_user_func si è rivelato esattamente ciò di cui avevo bisogno.
jay

44
call_user_funcnon è necessariamente necessario. È sempre possibile chiamare una funzione utilizzando funzioni variabili: $some_func(). call_user_func_arrayè quello che è veramente utile.
Ionuț G. Stan,

23
php ha sempre bisogno di "
cercare

2
@Pacerier errato. Le funzioni anonime sono ancora nelle variabili, ad es $func = function(){};. Qualsiasi possibile parametro per call_user_func deve essere richiamabile, il che significa che contiene dati sufficienti per accedervi direttamente, che sia $func(), o $obj->{$func}(), o qualsiasi altra cosa.
Benubird

2
Il "meno efficiente" è in realtà molto poco, soprattutto da php7, si tratta di pochi ms / milione di chiamate: github.com/fab2s/call_user_func
fab2s

32

Sebbene tu possa chiamare i nomi delle funzioni delle variabili in questo modo:

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

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

ci sono casi in cui non sai quanti argomenti stai passando. Considera quanto segue:

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

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

È anche utile per chiamare rispettivamente metodi statici e oggetto:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);

8
So che è vecchio di secoli, ma non sono riuscito a trovare articoli altrove. È più vantaggioso usare call_user_func ('customFunction') rispetto a $ variableFunction ()? Quali sono le differenze? Grazie!
David Hobs

15

l' call_user_funcopzione è lì così puoi fare cose come:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

dove la dynamicFunctionNamestringa potrebbe essere più eccitante e generata in fase di esecuzione. Non dovresti usare call_user_func a meno che non sia necessario, perché è più lento.


1
Sembra che potresti usare una funzione variabile in questo scenario.
Anthony Rutledge,

6

Immagino sia utile per chiamare una funzione di cui non conosci il nome in anticipo ... Qualcosa come:

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

call_user_func($func, 'stuff');

5
No. Possiamo ancora fare$func('stuff');
ankush981

1
Sì, ma la differenza è che l'utilizzo di una variabile produrrà un errore irreversibile PHP rispetto a un avviso PHP se viene utilizzato call_user_func.
Robert Brisita

Ciò non ha negato il valore delle funzioni variabili call_user_func()in questo scenario.
Anthony Rutledge,


3

Non ci sono vantaggi nel chiamare la funzione in questo modo perché penso che fosse principalmente utilizzata per chiamare la funzione "utente" (come il plugin) perché la modifica del file core non è una buona opzione. qui ci sono sporchi esempi usati da 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
?>

produzione

hello world my name is Tasikmalaya

0

nel tuo primo esempio stai usando il nome della funzione che è una stringa. potrebbe provenire dall'esterno o essere determinato al volo. cioè, non sai quale funzione dovrà essere eseguita al momento della creazione del codice.


-1

Quando si utilizzano gli spazi dei nomi, call_user_func () è l'unico modo per eseguire una funzione di cui non si conosce il nome in anticipo, ad esempio:

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

Se tutte le tue funzioni fossero nello stesso spazio dei nomi, non sarebbe un problema del genere, poiché potresti usare qualcosa del genere:

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

Modifica: seguendo @Jannis dicendo che mi sbaglio ho fatto un po 'più di test e non ho avuto molta fortuna:

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

Puoi vedere i risultati dell'output qui: https://3v4l.org/iBERh sembra che il secondo metodo funzioni per PHP 7 in poi, ma non PHP 5.6.


. per non essere vero. $ fn = '\ Foo \ Bar \ getCurrency'; $ fn ();
Jan Sverre

Ciao @Jannis, non trovo che sia vero, forse puoi vedere dove sto sbagliando, ho aggiunto un esempio più dettagliato alla mia risposta.
ThomasRedstone

@ThomasRedstone hai richiesto queste funzioni in anticipo? php non carica automaticamente le funzioni da altri file. Anche cosa c'è con quelle lettere piccole e grandi negli spazi dei nomi. Bar è una classe? allora questo è un altro caso d'uso.
przemo_li

ciao @przemo_li, questo è un singolo file (tutto all'interno dello spazio dei nomi), non sono sicuro di cosa sia successo con il nome dello spazio dei nomi, a mia difesa, ho scritto la risposta 4 anni fa, ho aggiornato lo spazio dei nomi e aggiunto in una nota su PHP 7, con un collegamento per vedere l'output effettivo. Non so ancora come ha fatto jansverre a funzionare, PHP 7 non è entrato in alpha fino all'11 giugno 2015
ThomasRedstone
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.