Mengakses variabel luar menggunakan fungsi anonim sebagai params

94

Pada dasarnya saya menggunakan fungsi praktis ini untuk memproses baris db (menutup mata pada PDO dan / atau hal-hal lain)

function fetch($query,$func) {
    $query = mysql_query($query);   
    while($r = mysql_fetch_assoc($query)) {
        $func($r);
    }
}

Dengan fungsi ini saya cukup melakukan:

fetch("SELECT title FROM tbl", function($r){
   //> $r['title'] contains the title
});

Katakanlah sekarang saya perlu menggabungkan semua $r['title']dalam var (ini hanya sebuah contoh).

Bagaimana saya bisa melakukan itu? Saya sedang memikirkan sesuatu seperti ini, tetapi tidak terlalu elegan:

$result = '';
fetch("SELECT title FROM tbl", function($r){
   global $result;
   $result .= $r['title'];
});

echo $result;
dinamis
sumber

Jawaban:

188

Anda harus menggunakan useseperti yang dijelaskan dalam dokumen :

Penutupan juga dapat mewarisi variabel dari lingkup induk. Variabel seperti itu harus dideklarasikan di header fungsi. Mewarisi variabel dari lingkup induk tidak sama dengan menggunakan variabel global. Variabel global ada dalam ruang lingkup global, yang sama tidak peduli fungsi apa yang dijalankan.

Kode:

$result = '';
fetch("SELECT title FROM tbl", function($r) use (&$result) {
   $result .= $r['title'];
});

Namun berhati-hatilah (diambil dari salah satu komentar di tautan sebelumnya):

Parameter use () adalah pengikatan awal - mereka menggunakan nilai variabel pada titik di mana fungsi lambda dideklarasikan, daripada titik di mana fungsi lambda dipanggil (pengikatan akhir).

Xaerxess
sumber
1
Bukankah perlambatan global itu harus dihilangkan?
aziz punjani
19
1 untuk menekankan early binding. Namun saya kira dalam contoh di atas ketika use (&$result)dilewatkan oleh referensi itu tidak masalah?
Dimitry K
4
@DimitryK Ya, referensi digunakan di sini untuk mengabaikan perilaku default (pengikatan awal).
Xaerxess
3
@machineaddict Dasarnya use adalah pengikatan awal - jika yang Anda maksud adalah solusi untuk pengikatan yang terlambat - Anda akan melewatkan variabel melalui usereferensi - menggunakan &=> use (&$result)dan mengubah $resultvariabel sebelum Anda memanggil fungsi anonim (atau sesuatu, yang menyebutnya)
jave.web
1
Karena instance kelas selalu diteruskan dengan referensi, Anda tidak perlu menggunakan & untuk mereka. (kecuali Anda benar-benar menimpa instance).
Joel Harkes
0

Bagaimana dengan menulis ulang 'fetch' untuk memanggil $ func hanya sekali?

function fetch($query,$func) {
    $query = mysql_query($query);   
    $retVal = array();
    while($r = mysql_fetch_assoc($query)) {
        $retVal[] = $r;
    }
    $func($retVal);
}

Dengan cara ini Anda akan memanggil $ func hanya sekali dan memproses ulang array setelah diambil? Tidak yakin dengan kinerjanya meskipun memanggil 200 kali suatu fungsi kedengarannya bukan ide yang bagus.

pengguna103307
sumber
Ya kamu benar. Namun, Anda dapat menggunakan mysql_fetch_row () daripada mysql_fetch_assoc () jika Anda tertarik untuk mendapatkan beberapa ms di sana-sini ... itu sangat sulit untuk ditangani karena Anda harus mengetahui posisi kolom Anda. Dengan demikian, Anda meneruskan dari 0.205 ke 0.180 pada 2000 permintaan dari 30 baris masing-masing.
user103307