Truy cập biến bên ngoài bằng cách sử dụng hàm ẩn danh làm tham số


93

Về cơ bản, tôi sử dụng chức năng tiện dụng này để xử lý các hàng db (nhắm mắt đến PDO và / hoặc những thứ khác)

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

Với chức năng này, tôi chỉ có thể làm:

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

Giả sử bây giờ tôi cần nối tất cả $r['title']trong một var (đây chỉ là một ví dụ).

Làm thế nào tôi có thể làm điều đó? Tôi đang nghĩ điều gì đó như thế này, nhưng nó không được thanh lịch cho lắm:

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

echo $result;

Câu trả lời:


188

Bạn phải sử dụng usenhư được mô tả trong tài liệu :

Closures cũng có thể kế thừa các biến từ phạm vi cha. Bất kỳ biến nào như vậy phải được khai báo trong tiêu đề hàm. Kế thừa các biến từ phạm vi cha không giống như sử dụng các biến toàn cục. Các biến toàn cục tồn tại trong phạm vi toàn cục, phạm vi này giống nhau cho dù hàm nào đang thực thi.

Mã:

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

Nhưng hãy cẩn thận (lấy từ một trong các bình luận trong liên kết trước):

Các tham số use () là liên kết sớm - chúng sử dụng giá trị của biến tại điểm mà hàm lambda được khai báo, chứ không phải tại điểm mà hàm lambda được gọi (liên kết muộn).


1
Không nên loại bỏ sự giảm tốc toàn cầu đó sao?
aziz punjani

19
+1 để nhấn mạnh early binding. Tuy nhiên, tôi đoán trong ví dụ trên khi nào use (&$result)được chuyển bằng tham chiếu nó không thực sự quan trọng?
Dimitry K

4
@DimitryK Có, tham chiếu được sử dụng ở đây để bỏ qua hành vi mặc định (liên kết sớm).
Xaerxess

3
@machineaddict Cơ bản use liên kết sớm - nếu bạn có nghĩa là giải pháp cho liên kết muộn - bạn sẽ chuyển biến qua usebằng cách tham chiếu - sử dụng &=> use (&$result)$resultbiến thay đổi trước khi bạn gọi hàm ẩn danh (hoặc một cái gì đó, gọi nó)
jave.web

1
Vì các thể hiện của lớp luôn được chuyển qua tham chiếu nên bạn sẽ không cần sử dụng & cho chúng. (trừ khi bạn ghi đè hoàn toàn cá thể).
Joel Harkes

0

Còn về việc viết lại 'fetch' để gọi $ func chỉ một lần?

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

Bằng cách này, bạn sẽ chỉ gọi $ func một lần và xử lý lại mảng sau khi được tìm nạp? Không chắc chắn về hiệu suất ngay cả khi bạn gọi 200 lần một hàm nghe có vẻ không phải là một ý kiến ​​hay.


Có bạn đúng. Tuy nhiên, bạn có thể sử dụng mysql_fetch_row () thay vì mysql_fetch_assoc () nếu bạn quan tâm đến việc đạt được một vài mili giây ở đây và ở đó ... nó thực sự rất khó để xử lý vì bạn phải biết vị trí cột của mình. Làm như vậy, bạn chuyển từ 0,205 đến 0,180 trên 2000 yêu cầu của mỗi hàng 30 hàng.
user103307
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.