Saya ingin dapat memanggil closure yang saya tetapkan ke properti objek secara langsung tanpa menetapkan ulang closure ke variabel dan kemudian memanggilnya. Apakah ini mungkin?
Kode di bawah ini tidak berfungsi dan menyebabkan Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
php
object
properties
closures
Kendall Hopkins
sumber
sumber
Jawaban:
Pada PHP7, Anda dapat melakukannya
atau gunakan Closure :: call () , meskipun itu tidak berfungsi pada a
StdClass
.Sebelum PHP7, Anda harus menerapkan
__call
metode ajaib untuk mencegat panggilan dan memanggil kembali (yangStdClass
tentu saja tidak mungkin , karena Anda tidak dapat menambahkan__call
metode)Perhatikan bahwa Anda tidak dapat melakukannya
dalam
__call
tubuh, karena ini akan memicu__call
dalam putaran tak terbatas.sumber
Anda bisa melakukan ini dengan memanggil __invoke pada closure, karena itulah metode ajaib yang digunakan objek untuk berperilaku seperti fungsi:
Tentu saja itu tidak akan berfungsi jika callback adalah larik atau string (yang juga bisa menjadi callback valid dalam PHP) - hanya untuk closure dan objek lain dengan perilaku __invoke.
sumber
call_user_func($obj->callback)
tidak seburuk itu.call_user_func
bekerja dengan string juga dan itu tidak selalu nyaman$obj->callback->__invoke();
diharapkan$obj->callback()
. Ini hanya masalah konsistensi.$obj->callback instanceof \Closure
.Mulai PHP 7, Anda dapat melakukan hal berikut:
sumber
Sejak PHP 7 penutupan dapat dipanggil menggunakan
call()
metode:Karena PHP 7 juga memungkinkan untuk menjalankan operasi pada
(...)
ekspresi sembarang (seperti yang dijelaskan oleh Korikulum ):Pendekatan umum PHP 5 lainnya adalah:
menggunakan metode ajaib
__invoke()
(seperti yang dijelaskan oleh Brilliand )menggunakan
call_user_func()
fungsi tersebutmenggunakan variabel perantara dalam ekspresi
Masing-masing cara memiliki pro dan kontranya masing-masing, namun solusi yang paling radikal dan pasti tetap yang dihadirkan oleh Gordon .
sumber
Sepertinya bisa digunakan
call_user_func()
.tidak elegan, meskipun .... Apa yang dikatakan @Gordon mungkin satu-satunya cara untuk pergi.
sumber
Nah, jika Anda benar-benar bersikeras. Solusi lain adalah:
Tapi itu bukan sintaks terbaik.
Namun, PHP parser selalu memperlakukan
T_OBJECT_OPERATOR
,IDENTIFIER
,(
sebagai metode panggilan. Tampaknya tidak ada solusi untuk membuat->
bypass tabel metode dan mengakses atribut sebagai gantinya.sumber
Saya tahu ini sudah tua, tapi saya pikir Sifat menangani masalah ini dengan baik jika Anda menggunakan PHP 5.4+
Pertama, buat sifat yang membuat properti bisa dipanggil:
Kemudian, Anda dapat menggunakan sifat itu di kelas Anda:
Sekarang, Anda dapat mendefinisikan properti melalui fungsi anonim dan memanggilnya secara langsung:
sumber
baik, harus ditekankan bahwa menyimpan closure dalam sebuah variabel, dan memanggil varible sebenarnya (anehnya) lebih cepat, tergantung pada jumlah panggilan, itu menjadi cukup banyak, dengan xdebug (pengukuran yang sangat tepat), kita sedang membicarakan 1,5 (faktor, dengan menggunakan varible, alih-alih langsung memanggil __invoke. Jadi sebagai gantinya, cukup simpan closure dalam varible dan panggil.
sumber
Diperbarui:
PHP> = 7:
PHP> = 5,4:
sumber
Call to undefined method AnyObject::callback()
(Kelas AnyObject ada, tentu saja.)Berikut alternatif lain berdasarkan jawaban yang diterima tetapi memperluas stdClass secara langsung:
Contoh penggunaan:
Anda mungkin lebih baik menggunakan
call_user_func
atau__invoke
meskipun.sumber
Jika Anda menggunakan PHP 5.4 atau yang lebih baru, Anda dapat mengikat callable ke cakupan objek Anda untuk menjalankan perilaku kustom. Jadi misalnya jika Anda memiliki pengaturan berikut ..
Dan Anda beroperasi di kelas seperti itu ..
Anda bisa menjalankan logika Anda sendiri seolah-olah Anda beroperasi dari dalam lingkup objek Anda
sumber
Saya perhatikan bahwa ini berfungsi di PHP5.5
Mengizinkan seseorang untuk membuat kumpulan objek psuedo dari penutupan.
sumber