PHP call_user_func vs. hanya memanggil fungsi

92

Saya yakin ada penjelasan yang sangat mudah untuk ini. Apa perbedaan antara ini:

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

... dan ini (dan apa manfaatnya?):

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

Jawaban:

88

Selalu gunakan nama fungsi yang sebenarnya jika Anda mengetahuinya.

call_user_func adalah untuk memanggil fungsi yang namanya tidak Anda ketahui sebelumnya, tetapi jauh kurang efisien karena program harus mencari fungsi tersebut saat runtime.

Kai
sumber
44
call_user_functidak selalu dibutuhkan. Anda selalu dapat memanggil fungsi dengan menggunakan fungsi variabel: $some_func(). call_user_func_arrayadalah salah satu yang sangat berguna.
Ionuț G. Stan
23
php selalu membutuhkan "untuk mencari fungsi saat runtime"
VolkerK
2
@Perier Salah. Fungsi anonim masih dalam variabel, yaitu $func = function(){};. Parameter apa pun yang mungkin untuk call_user_func harus dapat dipanggil, yang berarti berisi cukup data untuk mengaksesnya secara langsung, baik itu $func(), atau $obj->{$func}(), atau apa pun.
Benubird
2
"Kurang efisien" sebenarnya sangat sedikit, terutama karena php7, ini tentang beberapa md / juta panggilan: github.com/fab2s/call_user_func
fab2s
1
Menurut satu sumber , "memanggil fungsi yang tidak ada melalui variabel menyebabkan kesalahan fatal, sementara call_user_func () mengembalikan peringatan." Jadi itu satu perbedaan.
mbomb007
32

Meskipun Anda dapat memanggil nama fungsi variabel dengan cara ini:

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

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

ada kasus di mana Anda tidak tahu berapa banyak argumen yang Anda berikan. Pertimbangkan hal berikut:

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

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

Ini juga berguna untuk memanggil metode statis dan objek, masing-masing:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);
Lucas Oman
sumber
8
Saya tahu ini sudah sangat tua, tetapi tidak dapat menemukan artikel di tempat lain. Apakah lebih menguntungkan menggunakan call_user_func ('customFunction') sebagai apposed ke $ variableFunction ()? Apa perbedaannya? Terima kasih!
David Hobs
14

ada call_user_funcpilihan sehingga Anda dapat melakukan hal-hal seperti:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

dimana dynamicFunctionNamestring bisa lebih menarik dan dihasilkan pada saat run-time. Anda tidak boleh menggunakan call_user_func kecuali Anda harus melakukannya, karena ini lebih lambat.

Brian Schroth
sumber
2
Sepertinya Anda bisa menggunakan fungsi variabel dalam skenario ini.
Anthony Rutledge
5

Saya membayangkan ini berguna untuk memanggil fungsi yang Anda tidak tahu namanya sebelumnya ... Sesuatu seperti:

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

call_user_func($func, 'stuff');
sangat penting
sumber
6
Nggak. Kami masih bisa melakukannya$func('stuff');
ankush981
1
Ya, tetapi perbedaannya adalah menggunakan variabel akan menghasilkan kesalahan Fatal PHP versus peringatan PHP jika call_user_func digunakan.
Robert Brisita
Ini tidak meniadakan nilai fungsi variabel call_user_func()dalam skenario ini.
Anthony Rutledge
5

Dengan PHP 7 Anda dapat menggunakan sintaks fungsi variabel yang lebih bagus di mana-mana. Ia bekerja dengan fungsi statis / instan, dan dapat mengambil berbagai parameter. Info lebih lanjut di https://trowski.com/2015/06/20/php-callable-paradox

$ret = $callable(...$params);
mils
sumber
AFAICT, inilah satu-satunya jawaban yang benar-benar menjawab pertanyaan tersebut.
Mormegil
3

Tidak ada manfaat memanggil fungsi seperti itu karena menurut saya ini terutama digunakan untuk memanggil fungsi "pengguna" (seperti plugin) karena mengedit file inti bukanlah pilihan yang baik. berikut adalah contoh kotor yang digunakan oleh 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
?>

keluaran

hello world my name is Tasikmalaya
uingtea
sumber
0

dalam contoh pertama Anda, Anda menggunakan nama fungsi yang merupakan string. itu mungkin datang dari luar atau ditentukan dengan cepat. artinya, Anda tidak tahu fungsi apa yang perlu dijalankan pada saat pembuatan kode.

SilentGhost
sumber
-1

Saat menggunakan ruang nama, call_user_func () adalah satu-satunya cara untuk menjalankan fungsi yang namanya tidak Anda ketahui sebelumnya, misalnya:

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

Jika semua fungsi Anda berada di namespace yang sama, maka itu tidak akan menjadi masalah, karena Anda dapat menggunakan sesuatu seperti ini:

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

Sunting: Mengikuti @Jannis mengatakan bahwa saya salah, saya melakukan sedikit lebih banyak pengujian, dan tidak terlalu beruntung:

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

Anda dapat melihat hasil keluarannya di sini: https://3v4l.org/iBERh tampaknya metode kedua berfungsi untuk PHP 7 dan seterusnya, tetapi tidak untuk PHP 5.6.

ThomasRedstone
sumber
1
. karena tidak benar. $ fn = '\ Foo \ Bar \ getCurrency'; $ fn ();
Jan Sverre
Hai @Jannis, menurut saya itu tidak benar, mungkin Anda dapat melihat di mana kesalahan saya, saya telah menambahkan contoh yang lebih detail ke jawaban saya.
ThomasRedstone
@ThomasRedstone, apakah Anda memerlukan fungsi tersebut sebelumnya? php tidak memuat otomatis fungsi dari file lain. Juga ada apa dengan huruf kecil vs besar di ruang nama. Apakah Bar sebuah kelas? maka itu kasus penggunaan lainnya.
przemo_li
hai @przemo_li, ini adalah file tunggal (semua di dalam namespace), tidak yakin apa yang terjadi dengan nama namespace, dalam pembelaan saya, saya menulis jawabannya 4 tahun yang lalu, saya telah memperbarui namespace, dan menambahkan dalam catatan tentang PHP 7, dengan link untuk melihat hasil sebenarnya. Saya masih tidak tahu bagaimana jansverre membuatnya bekerja, PHP 7 tidak memasuki alpha hingga 11 Jun 2015
ThomasRedstone