Jawaban:
is_callable
fungsi ini. Ini akan memeriksa apakah variabel berisi sesuatu yang dapat disebut sebagai fungsi (baik itu nama fungsi, array yang berisi instance objek dan nama fungsi, atau fungsi / penutupan anonim)
call_user_func(array('ClassName', 'method'), $args)
Versi favorit saya adalah versi inline:
${"variableName"} = 12;
$className->{"propertyName"};
$className->{"methodName"}();
StaticClass::${"propertyName"};
StaticClass::{"methodName"}();
Anda dapat menempatkan variabel atau ekspresi di dalam tanda kurung juga!
{"functionName"}();
tidak sah dan akan menimbulkan kesalahan sintaksis.
Ya, itu mungkin:
function foo($msg) {
echo $msg."<br />";
}
$var1 = "foo";
$var1("testing 1,2,3");
Sumber: http://www.onlamp.com/pub/a/php/2001/05/17/php_foundations.html?page=2
Seperti yang telah disebutkan, ada beberapa cara untuk mencapai ini dengan kemungkinan metode teraman call_user_func()
atau jika Anda harus, Anda juga dapat menempuh jalan $function_name()
. Dimungkinkan untuk memberikan argumen menggunakan kedua metode ini seperti itu
$function_name = 'foobar';
$function_name(arg1, arg2);
call_user_func_array($function_name, array(arg1, arg2));
Jika fungsi yang Anda panggil milik objek Anda masih dapat menggunakan salah satu dari ini
$object->$function_name(arg1, arg2);
call_user_func_array(array($object, $function_name), array(arg1, arg2));
Namun jika Anda akan menggunakan $function_name()
metode ini mungkin ide yang baik untuk menguji keberadaan fungsi jika namanya dinamis
if(method_exists($object, $function_name))
{
$object->$function_name(arg1, arg2);
}
Jika ada orang lain yang dibawa ke sini oleh google karena mereka mencoba menggunakan variabel untuk metode di dalam kelas, di bawah ini adalah contoh kode yang benar-benar akan berfungsi. Tidak satu pun di atas yang berfungsi untuk situasi saya. Perbedaan utama adalah &
dalam deklarasi $c = & new...
dan &$c
disahkan call_user_func
.
Kasus spesifik saya adalah ketika menerapkan kode seseorang yang berkaitan dengan warna dan dua metode anggota lighten()
dan darken()
dari kelas csscolor.php. Untuk alasan apa pun, saya ingin memiliki kode yang sama dapat memanggil terang atau gelap daripada memilihnya dengan logika. Ini mungkin hasil dari kekeraskepalaan saya untuk tidak hanya menggunakan if-else atau mengubah kode yang memanggil metode ini.
$lightdark="lighten"; // or optionally can be darken
$color="fcc"; // a hex color
$percent=0.15;
include_once("csscolor.php");
$c = & new CSS_Color($color);
$rtn=call_user_func( array(&$c,$lightdark),$color,$percent);
Perhatikan bahwa mencoba apa pun dengan $c->{...}
tidak berhasil. Setelah membaca konten yang disumbangkan pembaca di bagian bawah halaman php.net call_user_func
, saya dapat menyatukannya di atas. Perhatikan juga bahwa $params
sebagai array tidak berfungsi untuk saya:
// This doesn't work:
$params=Array($color,$percent);
$rtn=call_user_func( array(&$c,$lightdark),$params);
Upaya di atas akan memberikan peringatan tentang metode yang mengharapkan argumen ke-2 (persen).
Beberapa tahun terlambat, tetapi ini adalah cara terbaik sekarang imho:
$x = (new ReflectionFunction("foo"))->getClosure();
$x();
Demi kelengkapan, Anda juga dapat menggunakan eval () :
$functionName = "foo()";
eval($functionName);
Namun, call_user_func()
itu cara yang tepat.
eval
bukan solusi untuk pertanyaan ini.
Catatan: Untuk versi yang diringkas, lihat TL; DR di akhir jawaban.
Pembaruan : Salah satu metode lama yang dijelaskan di sini telah dihapus. Lihat jawaban lain untuk penjelasan tentang metode lain, itu tidak dibahas di sini. Ngomong-ngomong, jika jawaban ini tidak membantu Anda, Anda harus kembali memperbarui barang-barang Anda. Dukungan PHP 5.6 telah berakhir pada Januari 2019 (sekarang bahkan PHP 7.0 dan 7.1 tidak didukung). Lihat versi yang didukung untuk informasi lebih lanjut.
Seperti yang disebutkan lainnya, dalam PHP5 (dan juga dalam versi yang lebih baru seperti PHP7) kita bisa menggunakan variabel sebagai nama fungsi, menggunakan call_user_func()
dan call_user_func_array()
(yang, secara pribadi, saya benci fungsi-fungsi itu), dll.
Pada PHP7, ada cara baru yang diperkenalkan:
Catatan: Segala sesuatu di dalam <something>
tanda kurung berarti satu atau lebih ekspresi untuk membentuk sesuatu, misalnya <function_name>
ekspresi yang membentuk nama fungsi.
Kita dapat menggunakan satu atau lebih ekspresi di dalam tanda kurung sebagai nama fungsi hanya dalam sekali jalan, dalam bentuk:
(<function_name>)(arguments);
Sebagai contoh:
function something(): string
{
return "something";
}
$bar = "some_thing";
(str_replace("_", "", $bar))(); // something
// Possible, too; but generally, not recommended, because makes your code more complicated
(str_replace("_", "", $bar))()();
Catatan: Meskipun menghapus tanda kurung str_replace()
bukanlah kesalahan, menempatkan tanda kurung membuat kode lebih mudah dibaca. Namun, Anda terkadang tidak dapat melakukannya, misalnya saat menggunakan .
operator. Agar konsisten, saya sarankan Anda untuk selalu menempatkan tanda kurung.
Sama seperti panggilan fungsi dinamis, kita dapat melakukan hal yang sama dengan pemanggilan metode, dikelilingi oleh kurung kurawal alih-alih tanda kurung (untuk formulir tambahan, navigasikan ke TL; bagian DR):
$object->{<method_name>}(arguments);
$object::{<method_name>}(arguments);
Lihat dalam contoh:
class Foo
{
public function another(): string
{
return "something";
}
}
$bar = "another thing";
(new Something())->{explode(" ", $bar)[0]}(); // something
Cara yang lebih elegan ditambahkan di PHP7 adalah sebagai berikut:
[<object>, <method_name>](arguments);
[<class_name>, <method_name>](arguments); // Static calls only
Sebagai contoh:
class Foo
{
public function nonStaticCall()
{
echo "Non-static call";
}
public static function staticCall()
{
echo "Static call";
}
}
$x = new X();
[$x, "non" . "StaticCall"](); // Non-static call
[$x, "static" . "Call"](); // Static call
Catatan: Manfaat menggunakan metode ini daripada yang sebelumnya adalah, Anda tidak peduli dengan jenis panggilan (yaitu apakah itu statis atau tidak).
Membuat segalanya sedikit rumit, Anda bisa menggunakan kombinasi kelas anonim dan fitur di atas:
$bar = "SomeThing";
echo (new class {
public function something()
{
return 512;
}
})->{strtolower($bar)}(); // 512
Secara umum, di PHP7, menggunakan formulir berikut ini dimungkinkan:
// Everything inside `<something>` brackets means one or more expressions
// to form something
// Dynamic function call
(<function_name>)(arguments)
// Dynamic method call on an object
$object->{<method_name>}(arguments)
$object::{<method_name>}(arguments)
// Dynamic method call on a dynamically-generated object
(<object>)->{<method_name>}(arguments)
(<object>)::{<method_name>}(arguments)
// Dynamic method call, statically
ClassName::{<method_name>}(arguments)
(<class_name>)::{<method_name>}(arguments)
// Dynamic method call, array-like (no different between static and non-static calls
[<object>, <method_name>](arguments)
// Dynamic method call, array-like, statically
[<class_name>, <method_name>](arguments)
Sebagian besar didasarkan pada pembicaraan PHP ini .
(expressions)->$bar()
Hanya untuk menambahkan titik tentang nama fungsi dinamis saat menggunakan ruang nama.
Jika Anda menggunakan ruang nama, yang berikut ini tidak akan berfungsi kecuali jika fungsi Anda ada di ruang nama global:
namespace greetings;
function hello()
{
// do something
}
$myvar = "hello";
$myvar(); // interpreted as "\hello();"
Anda harus menggunakan call_user_func()
sebagai gantinya:
// if hello() is in the current namespace
call_user_func(__NAMESPACE__.'\\'.$myvar);
// if hello() is in another namespace
call_user_func('mynamespace\\'.$myvar);
Melengkapi jawaban @Chris K jika Anda ingin memanggil metode objek, Anda dapat menyebutnya menggunakan variabel tunggal dengan bantuan penutupan:
function get_method($object, $method){
return function() use($object, $method){
$args = func_get_args();
return call_user_func_array(array($object, $method), $args);
};
}
class test{
function echo_this($text){
echo $text;
}
}
$test = new test();
$echo = get_method($test, 'echo_this');
$echo('Hello'); //Output is "Hello"
Saya memposting contoh lain di sini
Katakanlah saya memiliki variabel dan fungsi ini:
$functionName1 = "sayHello";
$functionName2 = "sayHelloTo";
$functionName3 = "saySomethingTo";
$friend = "John";
$datas = array(
"something"=>"how are you?",
"to"=>"Sarah"
);
function sayHello()
{
echo "Hello!";
}
function sayHelloTo($to)
{
echo "Dear $to, hello!";
}
function saySomethingTo($something, $to)
{
echo "Dear $to, $something";
}
Untuk memanggil fungsi tanpa argumen
// Calling sayHello()
call_user_func($functionName1);
Halo!
Untuk memanggil fungsi dengan 1 argumen
// Calling sayHelloTo("John")
call_user_func($functionName2, $friend);
John terkasih, halo!
Untuk memanggil fungsi dengan 1 argumen atau lebih
Ini akan berguna jika Anda memanggil fungsi Anda secara dinamis dan setiap fungsi memiliki jumlah argumen yang berbeda. Ini adalah kasus saya yang saya cari (dan selesaikan). call_user_func_array
adalah kuncinya
// You can add your arguments
// 1. statically by hard-code,
$arguments[0] = "how are you?"; // my $something
$arguments[1] = "Sarah"; // my $to
// 2. OR dynamically using foreach
$arguments = NULL;
foreach($datas as $data)
{
$arguments[] = $data;
}
// Calling saySomethingTo("how are you?", "Sarah")
call_user_func_array($functionName3, $arguments);
Sarah sayang, bagaimana kabarmu?
Yay sampai jumpa!
Gunakan fungsi call_user_func.
Kode berikut dapat membantu menulis fungsi dinamis dalam PHP. sekarang nama fungsi dapat diubah secara dinamis dengan variabel '$ current_page'.
$current_page = 'home_page';
$function = @${$current_page . '_page_versions'};
$function = function() {
echo 'current page';
};
$function();
$function
variabel tanpa alasan apa pun.
Cara termudah untuk memanggil suatu fungsi dengan aman menggunakan nama yang disimpan dalam variabel adalah,
//I want to call method deploy that is stored in functionname
$functionname = 'deploy';
$retVal = {$functionname}('parameters');
Saya telah menggunakan seperti di bawah ini untuk membuat tabel migrasi di Laravel secara dinamis,
foreach(App\Test::$columns as $name => $column){
$table->{$column[0]}($name);
}
Salah satu pendekatan yang tidak konvensional, yang muncul di benak saya adalah, kecuali jika Anda menghasilkan seluruh kode melalui beberapa super otonom AI yang menulis sendiri , ada kemungkinan besar bahwa fungsi yang Anda ingin panggilan "dinamis", sudah ditentukan dalam kode Anda mendasarkan. Jadi mengapa tidak memeriksa string dan melakukan ifelse
tarian terkenal untuk memanggil ... Anda mengerti maksud saya.
misalnya.
if($functionName == 'foo'){
foo();
} else if($functionName == 'bar'){
bar();
}
Bahkan switch-case
dapat digunakan jika Anda tidak menyukai rasa ifelse
tangga yang hambar .
Saya mengerti bahwa ada kasus di mana " memanggil fungsi secara dinamis " akan menjadi kebutuhan mutlak ( Seperti beberapa logika rekursif yang memodifikasi sendiri ). Tetapi sebagian besar kasus penggunaan sepele sehari-hari hanya bisa dihindari.
Ini menghilangkan banyak ketidakpastian dari aplikasi Anda, sambil memberi Anda kesempatan untuk mengeksekusi fungsi mundur jika string tidak cocok dengan definisi fungsi yang tersedia. MENURUT OPINI SAYA.
if (method_exists($functionName)) $functionName(); else //exception or handle
Saya tidak tahu mengapa Anda harus menggunakan itu, sama sekali tidak terdengar baik bagi saya, tetapi jika hanya ada sedikit fungsi, Anda bisa menggunakan if / else jika membangun. Saya tidak tahu apakah solusi langsung mungkin.
sesuatu seperti $ foo = "bar"; $ test = "foo"; tes echo $$;
harus mengembalikan bar, Anda dapat mencoba tetapi saya tidak berpikir ini akan berfungsi untuk fungsi