Akan menghubungkan pertanyaan lain dengan yang ini, karena saya mencoba menelepon penutupan.
akinuri
Jawaban:
173
Manual menggunakan istilah "callback" dan "callable" secara bergantian, namun, "callback" secara tradisional mengacu pada nilai string atau array yang bertindak seperti penunjuk fungsi , referensi fungsi atau metode kelas untuk doa selanjutnya. Ini telah memungkinkan beberapa elemen pemrograman fungsional sejak PHP 4. Rasa adalah:
$cb1 ='someGlobalFunction';
$cb2 =['ClassName','someStaticMethod'];
$cb3 =[$object,'somePublicMethod'];// this syntax is callable since PHP 5.2.3 but a string containing it// cannot be called directly
$cb2 ='ClassName::someStaticMethod';
$cb2();// fatal error// legacy syntax for PHP 4
$cb3 = array(&$object,'somePublicMethod');
Ini adalah cara yang aman untuk menggunakan nilai-nilai yang bisa dipanggil pada umumnya:
if(is_callable($cb2)){// Autoloading will be invoked to load the class "ClassName" if it's not// yet defined, and PHP will check that the class has a method// "someStaticMethod". Note that is_callable() will NOT verify that the// method can safely be executed in static context.
$returnValue = call_user_func($cb2, $arg1, $arg2);}
Versi PHP modern memungkinkan tiga format pertama di atas untuk dipanggil secara langsung sebagai $cb(). call_user_funcdan call_user_func_arraymendukung semua hal di atas.
Jika fungsi / kelas di-namespace, string harus berisi nama yang sepenuhnya memenuhi syarat. Misalnya['Vendor\Package\Foo', 'method']
call_user_functidak mendukung lewat non-objek dengan referensi, sehingga Anda bisa menggunakan call_user_func_arrayatau, dalam versi PHP kemudian, menyimpan callback untuk var dan menggunakan sintaks langsung: $cb();
Objek dengan __invoke()metode (termasuk fungsi anonim) termasuk dalam kategori "bisa dipanggil" dan dapat digunakan dengan cara yang sama, tapi saya pribadi tidak mengaitkan ini dengan istilah "panggilan balik" lama.
Warisan create_function()menciptakan fungsi global dan mengembalikan namanya. Ini pembungkus untuk eval()dan fungsi anonim harus digunakan sebagai gantinya.
Memang, menggunakan fungsi adalah cara yang tepat untuk melakukannya. Saat menggunakan variabel dan kemudian memanggilnya, seperti yang disarankan dalam jawaban yang diterima itu keren, itu jelek dan tidak akan skala dengan kode.
icco
4
Mengubah jawaban yang diterima. Setuju dengan komentar, ini adalah jawaban yang bagus.
Nick Stinemates
Akan sangat membantu bagi pembaca yang datang dari pemrograman Python untuk menunjukkan jawaban yang 'someGlobalFunction'memang merupakan fungsi yang didefinisikan.
TMOTTM
1
Pada PHP 5.3, ada penutupan, lihat jawaban Bart van Heukelom . Ini jauh lebih sederhana dan "standar" daripada semua kekacauan warisan ini.
reallynice
Ya, saya menyebutkan fungsi anonim dalam jawaban saya, tetapi OP meminta "panggilan balik" (pada 2008) dan panggilan balik gaya lama ini masih sangat banyak digunakan dalam banyak basis kode PHP.
Steve Clay
74
Dengan PHP 5.3, Anda sekarang dapat melakukan ini:
function doIt($callback){ $callback();}
doIt(function(){// this will be done});
Akhirnya cara yang bagus untuk melakukannya. Tambahan yang bagus untuk PHP, karena panggilan baliknya mengagumkan.
Implementasi panggilan balik dilakukan seperti itu
// This function uses a callback function. function doIt($callback){
$data ="this is my data";
$callback($data);}// This is a sample callback function for doIt(). function myCallback($data){print'Data is: '. $data ."\n";}// Call doIt() and pass our sample callback function's name.
doIt('myCallback');
Ada beberapa cara lain untuk melakukannya seperti yang ditunjukkan di atas. Saya benar-benar memikirkan hal yang sama.
Nick Stinemates
3
@Nick Retallack, saya tidak melihat apa yang mengerikan tentangnya. Untuk bahasa yang saya tahu, seperti JavaScript dan C #, mereka semua dapat menyusun fungsi panggilan balik mereka dalam pola tersebut. Berasal dari JavaScirpt dan C #, saya benar-benar tidak terbiasa dengan call_user_func (). Itu membuat saya merasa harus beradaptasi dengan PHP, bukan sebaliknya.
Antony
4
@Antony Saya keberatan dengan fakta bahwa string adalah pointer fungsi dalam bahasa ini. Saya memposting komentar itu tiga tahun yang lalu, jadi saya sudah terbiasa sekarang, tapi saya pikir PHP adalah satu-satunya bahasa yang saya tahu (selain dari skrip shell) di mana ini terjadi.
Nick Retallack
1
@Antony Saya lebih suka menggunakan sintaks yang sama yang saya gunakan dalam javascript. Jadi saya bahkan tidak mengerti mengapa orang ingin menggunakan call_user_func()Ketika mereka memiliki sintaks yang memungkinkan mereka untuk secara dinamis memanggil fungsi dan membuat panggilan balik. Saya setuju denganmu!
botenvouwer
9
Satu trik bagus yang baru-baru ini saya temukan adalah menggunakan PHP create_function()untuk membuat fungsi anonim / lambda untuk penggunaan sekali pakai. Ini berguna untuk fungsi PHP seperti array_map(), preg_replace_callback()atau usort()bahwa penggunaan callback untuk pengolahan kustom. Ini terlihat seperti itu di eval()bawah selimut, tapi itu masih cara gaya fungsional yang bagus untuk menggunakan PHP.
Sayangnya, pengumpul sampah tidak bermain dengan baik dengan konstruksi ini yang menghasilkan kebocoran memori potensial. Jika Anda keluar untuk kinerja, hindari create_function ().
fuxia
1
Aduh. Terimakasih atas peringatannya.
yukondude
Maukah Anda memperbarui jawaban dengan versi PHP 7.4 (fungsi panah) dan menambahkan peringatan tentang usang create_function()?
Dharman
7
baik ... dengan 5.3 di cakrawala, semua akan lebih baik, karena dengan 5.3, kita akan mendapatkan penutupan dan dengan mereka fungsi anonim
Anda akan ingin memverifikasi apa pun panggilan Anda valid. Misalnya, dalam hal fungsi tertentu, Anda akan ingin memeriksa dan melihat apakah fungsi tersebut ada:
function doIt($callback){if(function_exists($callback)){
$callback();}else{// some error handling}}
Bagaimana jika callback bukan fungsi, tetapi sebuah array yang menahan objek dan metode?
d -_- b
3
atau lebih tepatnyais_callable( $callback )
Roko C. Buljan
1
Keduanya adalah saran yang bagus - Anda perlu memeriksa implementasi khusus Anda sendiri tentang bagaimana Anda melakukan panggilan balik. Saya berharap untuk memperingatkan agar tidak memanggil sesuatu yang tidak ada yang menyebabkan kematian. Saya membuat jawabannya lebih umum
SeanDowney
5
create_functiontidak bekerja untuk saya di dalam kelas. Saya harus menggunakan call_user_func.
Bukankah kelas Dispatcher memerlukan atribut untuk $ this-> callback = $ callback untuk berfungsi?
James P.
@james poulson: PHP adalah bahasa yang dinamis, jadi ia berfungsi. Tapi saya malas. Saya biasanya mendeklarasikan properti, membuat hidup semua orang lebih mudah. Pertanyaan Anda membuat saya melihat kode itu lagi dan melihat kesalahan sintaksis, Anda. Terima kasih
goliatone
Saya tidak tahu ini mungkin. Terima kasih atas jawabannya :) .
James P.
Bukankah lebih aman untuk mendeklarasikan fungsi do_callback sebelum membuat objek Dispatcher dan memanggil metode async?
ejectamenta
3
Saya merasa ngeri setiap kali saya menggunakan create_function()php.
Parameter adalah string yang dipisahkan koma, seluruh fungsi tubuh dalam sebuah string ... Argh ... Saya pikir mereka tidak bisa membuatnya lebih buruk bahkan jika mereka mencoba.
Sayangnya, itu adalah satu-satunya pilihan ketika membuat fungsi bernama tidak sebanding dengan masalahnya.
Dan, tentu saja, ini string runtime eval, jadi itu tidak diperiksa untuk sintaks yang valid atau apa pun pada waktu kompilasi.
hobbs
Jawaban ini telah usang selama 2 tahun terakhir. create_function()sekarang sudah usang dan tidak boleh digunakan.
Dharman
2
Bagi mereka yang tidak peduli tentang melanggar kompatibilitas dengan PHP < 5.4, saya sarankan menggunakan tipe hinting untuk membuat implementasi yang lebih bersih.
function call_with_hello_and_append_world( callable $callback ){// No need to check $closure because of the type hintreturn $callback("hello")."world";}function append_space( $string ){return $string." ";}
$output1 = call_with_hello_and_append_world(function( $string ){return $string." ";});
var_dump( $output1 );// string(11) "hello world"
$output2 = call_with_hello_and_append_world("append_space");
var_dump( $output2 );// string(11) "hello world"
$old_lambda = create_function('$string','return $string." ";');
$output3 = call_with_hello_and_append_world( $old_lambda );
var_dump( $output3 );// string(11) "hello world"
Jawaban:
Manual menggunakan istilah "callback" dan "callable" secara bergantian, namun, "callback" secara tradisional mengacu pada nilai string atau array yang bertindak seperti penunjuk fungsi , referensi fungsi atau metode kelas untuk doa selanjutnya. Ini telah memungkinkan beberapa elemen pemrograman fungsional sejak PHP 4. Rasa adalah:
Ini adalah cara yang aman untuk menggunakan nilai-nilai yang bisa dipanggil pada umumnya:
Versi PHP modern memungkinkan tiga format pertama di atas untuk dipanggil secara langsung sebagai
$cb()
.call_user_func
dancall_user_func_array
mendukung semua hal di atas.Lihat: http://php.net/manual/en/language.types.callable.php
Catatan / Peringatan:
['Vendor\Package\Foo', 'method']
call_user_func
tidak mendukung lewat non-objek dengan referensi, sehingga Anda bisa menggunakancall_user_func_array
atau, dalam versi PHP kemudian, menyimpan callback untuk var dan menggunakan sintaks langsung:$cb()
;__invoke()
metode (termasuk fungsi anonim) termasuk dalam kategori "bisa dipanggil" dan dapat digunakan dengan cara yang sama, tapi saya pribadi tidak mengaitkan ini dengan istilah "panggilan balik" lama.create_function()
menciptakan fungsi global dan mengembalikan namanya. Ini pembungkus untukeval()
dan fungsi anonim harus digunakan sebagai gantinya.sumber
'someGlobalFunction'
memang merupakan fungsi yang didefinisikan.Dengan PHP 5.3, Anda sekarang dapat melakukan ini:
Akhirnya cara yang bagus untuk melakukannya. Tambahan yang bagus untuk PHP, karena panggilan baliknya mengagumkan.
sumber
Implementasi panggilan balik dilakukan seperti itu
Menampilkan: Data adalah: ini adalah data saya
sumber
call_user_func()
Ketika mereka memiliki sintaks yang memungkinkan mereka untuk secara dinamis memanggil fungsi dan membuat panggilan balik. Saya setuju denganmu!Satu trik bagus yang baru-baru ini saya temukan adalah menggunakan PHP
create_function()
untuk membuat fungsi anonim / lambda untuk penggunaan sekali pakai. Ini berguna untuk fungsi PHP sepertiarray_map()
,preg_replace_callback()
atauusort()
bahwa penggunaan callback untuk pengolahan kustom. Ini terlihat seperti itu dieval()
bawah selimut, tapi itu masih cara gaya fungsional yang bagus untuk menggunakan PHP.sumber
create_function()
?baik ... dengan 5.3 di cakrawala, semua akan lebih baik, karena dengan 5.3, kita akan mendapatkan penutupan dan dengan mereka fungsi anonim
http://wiki.php.net/rfc/closures
sumber
Anda akan ingin memverifikasi apa pun panggilan Anda valid. Misalnya, dalam hal fungsi tertentu, Anda akan ingin memeriksa dan melihat apakah fungsi tersebut ada:
sumber
is_callable( $callback )
create_function
tidak bekerja untuk saya di dalam kelas. Saya harus menggunakancall_user_func
.Lalu, untuk menggunakan:
[Sunting] Menambahkan tanda kurung yang hilang. Juga, menambahkan deklarasi panggilan balik, saya lebih suka seperti itu.
sumber
Saya merasa ngeri setiap kali saya menggunakan
create_function()
php.Parameter adalah string yang dipisahkan koma, seluruh fungsi tubuh dalam sebuah string ... Argh ... Saya pikir mereka tidak bisa membuatnya lebih buruk bahkan jika mereka mencoba.
Sayangnya, itu adalah satu-satunya pilihan ketika membuat fungsi bernama tidak sebanding dengan masalahnya.
sumber
create_function()
sekarang sudah usang dan tidak boleh digunakan.Bagi mereka yang tidak peduli tentang melanggar kompatibilitas dengan PHP
< 5.4
, saya sarankan menggunakan tipe hinting untuk membuat implementasi yang lebih bersih.sumber
create_function()
telah DITANGGUHKAN pada PHP 7.2.0. Mengandalkan fungsi ini sangat tidak dianjurkan.