Menggunakan `$ this` dalam fungsi anonim di PHP sebelum 5.4.0

86

Status manual PHP

Tidak mungkin digunakan $thisdari fungsi anonim sebelum PHP 5.4.0

di halaman fungsi anonim . Tetapi saya telah menemukan bahwa saya dapat membuatnya bekerja dengan menetapkan $thiske variabel dan meneruskan variabel ke usepernyataan pada definisi fungsi.

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

Apakah ini praktik yang baik?
Apakah ada cara yang lebih baik untuk mengakses $thisdi dalam fungsi anonim menggunakan PHP 5.3?

ditenagai uap
sumber
1
Hanya konvensi forum kecil - biasanya lebih baik menerima jawaban daripada mengedit pertanyaan untuk mencerminkan jawaban pilihan Anda. Ini terutama agar tanggapan tetap masuk akal untuk selamanya, tetapi juga tentu saja memberikan penghargaan untuk jawaban yang benar.
halfer
4
Berhati-hatilah $CI = $this;dan sebenarnya $CI =& $this; tidak identik. Mungkin untuk tujuan Anda, tetapi keduanya tidak sama. Coba $CI = 'bla'; var_dump($this);dengan kedua versi untuk melihat perbedaannya.
Rudie
1
@ Rudie Saya menambahkan dokumentasi untuk komentar Anda
steampowered
@steampowered Ada contoh / artikel bagus online di suatu tempat tentang ini, tapi saya tidak dapat menemukannya =) Maaf. Coba saja jika Anda tidak melihat perbedaannya. Itu sudah jelas.
Rudie

Jawaban:

67

Ini akan gagal ketika Anda mencoba memanggil metode yang dilindungi atau privat di atasnya, karena menggunakannya dengan cara itu dihitung sebagai panggilan dari luar. Sejauh yang saya tahu, tidak ada cara untuk mengatasi ini di 5.3, tetapi datanglah PHP 5.4, ini akan berfungsi seperti yang diharapkan, di luar kotak:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}
$hello = new Hello();
$helloPrinter = $hello->createClosure();
$helloPrinter(); // outputs "Hello world"

Terlebih lagi, Anda akan dapat mengubah ke mana $ this menunjuk pada waktu proses, untuk fungsi anonymus (penutupan kembali):

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}

class Bye {

    private $message = "Bye world\n";

}

$hello = new Hello();
$helloPrinter = $hello->createClosure();

$bye = new Bye();
$byePrinter = $helloPrinter->bindTo($bye, $bye);
$byePrinter(); // outputs "Bye world"

Secara efektif, fungsi anonymus akan memiliki metode bindTo () , di mana parameter pertama dapat digunakan untuk menentukan ke mana $ this menunjuk, dan parameter kedua mengontrol level visibilitas yang seharusnya . Jika Anda menghilangkan parameter kedua, visibilitas akan seperti memanggil dari "luar", misalnya. hanya properti publik yang dapat diakses. Juga catat cara kerja bindTo, ini tidak mengubah fungsi aslinya, ia mengembalikan yang baru .

K. Norbert
sumber
1
Menandai jawaban Anda dengan benar, tetapi hanya untuk memperjelas bagi pembaca lain: konvensi yang digunakan dalam pertanyaan akan berfungsi untuk metode publik yang menggunakan objek yang merujuk $this.
steampowered
5
Metode non-publik dapat diakses dengan menggunakan refleksi. Tidak efisien dan sedikit jahat, tetapi berhasil.
keluar
7

Jangan selalu mengandalkan PHP untuk meneruskan objek dengan referensi, saat Anda menetapkan referensi itu sendiri, perilakunya tidak sama seperti di sebagian besar bahasa OO di mana pointer asli dimodifikasi.

contoh Anda:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

seharusnya:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

CATATAN REFERENSI "&" dan $ CI harus ditetapkan setelah panggilan terakhir pada itu telah dilakukan, sekali lagi Anda mungkin memiliki keluaran yang tidak dapat diprediksi, dalam PHP mengakses referensi tidak selalu sama dengan mengakses kelas asli - jika itu masuk akal.

http://php.net/manual/en/language.references.pass.php

Christof Coetzee
sumber
6

Itu adalah cara yang biasa dilakukan.
btw, coba untuk menghapus &itu seharusnya bekerja tanpa ini, sebagai objek melewati ref dengan cara apapun.

Itay Moav -Malimovka
sumber
1

Tampaknya baik-baik saja jika referensi lewat Anda itu cara yang benar untuk melakukannya. Jika Anda menggunakan PHP 5, Anda tidak memerlukan &simbol sebelumnya $thiskarena itu akan selalu melewati referensi.

api
sumber
2
OP harus menggunakan 5.3 atau lebih besar, karena 4.x tidak mendukung fungsi anonim :-)
halfer
1

Ini bagus. Menurut saya, Anda juga bisa melakukan ini:

$CI = $this;

... karena penugasan yang melibatkan objek akan selalu menyalin referensi, bukan seluruh objek.

halfer
sumber