การเข้าถึงตัวแปรภายนอกโดยใช้ฟังก์ชันนิรนามเป็นพารามิเตอร์


95

โดยทั่วไปฉันใช้ฟังก์ชันที่มีประโยชน์นี้เพื่อประมวลผลแถว db (ปิดตาที่ PDO และ / หรือสิ่งอื่น ๆ )

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

ด้วยฟังก์ชั่นนี้ฉันสามารถทำได้:

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

สมมติว่าตอนนี้ฉันต้องการเชื่อมต่อทั้งหมด$r['title']ใน var (นี่เป็นเพียงตัวอย่าง)

ฉันจะทำอย่างนั้นได้อย่างไร? ฉันกำลังคิดอะไรแบบนี้ แต่มันก็ไม่ได้สวยหรูมากนัก:

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

echo $result;

คำตอบ:


191

คุณต้องใช้useตามที่อธิบายไว้ในเอกสาร :

การปิดอาจสืบทอดตัวแปรจากขอบเขตหลัก ต้องประกาศตัวแปรดังกล่าวในส่วนหัวของฟังก์ชัน การรับตัวแปรจากขอบเขตหลักไม่เหมือนกับการใช้ตัวแปรส่วนกลาง ตัวแปรส่วนกลางมีอยู่ในขอบเขตส่วนกลางซึ่งเหมือนกันไม่ว่าฟังก์ชันใดจะเรียกใช้งาน

รหัส:

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

แต่ระวัง (นำมาจากหนึ่งในความคิดเห็นในลิงค์ก่อนหน้า):

พารามิเตอร์ use () เป็นการเชื่อมโยงในช่วงต้น - ใช้ค่าของตัวแปร ณ จุดที่มีการประกาศฟังก์ชันแลมบ์ดาแทนที่จะเป็นจุดที่เรียกใช้ฟังก์ชันแลมบ์ดา (การผูกปลาย)


1
ไม่ควรลบการชะลอตัวทั่วโลก?
aziz punjani

19
+1 สำหรับเน้นearly binding. อย่างไรก็ตามฉันเดาว่าในตัวอย่างข้างต้นเมื่อuse (&$result)ถูกส่งผ่านโดยการอ้างอิงมันไม่สำคัญจริงเหรอ?
Dimitry K

4
@DimitryK ใช่การอ้างอิงถูกใช้ที่นี่เพื่อข้ามพฤติกรรมเริ่มต้น (การเชื่อมโยงในช่วงต้น)
Xaerxess

3
@machineaddict พื้นฐานuse คือการเชื่อมโยงก่อนกำหนด - หากคุณหมายถึงวิธีแก้ปัญหาสำหรับการเชื่อมโยงล่าช้า - คุณจะส่งผ่านตัวแปรuseโดยการอ้างอิง - โดยใช้&=> use (&$result)และแก้ไข$resultตัวแปรก่อนที่คุณจะเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อ (หรือบางสิ่งที่เรียกมัน)
jave.web

1
เนื่องจากอินสแตนซ์ของคลาสจะถูกส่งผ่านโดยการอ้างอิงเสมอคุณจึงไม่จำเป็นต้องใช้ & สำหรับอินสแตนซ์เหล่านี้ (เว้นแต่คุณจะเขียนทับอินสแตนซ์ทั้งหมด)
Joel Harkes

0

สิ่งที่เกี่ยวกับการเขียน 'ดึงข้อมูล' เพื่อเรียก $ func เพียงครั้งเดียว?

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

ด้วยวิธีนี้คุณจะเรียก $ func เพียงครั้งเดียวและประมวลผลอาร์เรย์ใหม่เมื่อดึงข้อมูลแล้ว? ไม่แน่ใจเกี่ยวกับประสิทธิภาพแม้กระทั่งการโทร 200 ครั้งฟังก์ชั่นก็ไม่ได้เป็นความคิดที่ดี


ใช่คุณถูก. อย่างไรก็ตามคุณสามารถใช้ mysql_fetch_row () แทน mysql_fetch_assoc () ได้หากคุณสนใจที่จะได้รับสองสามมิลลิวินาทีที่นี่และที่นั่น ... มันยากมากที่จะจัดการเพราะคุณต้องรู้ตำแหน่งคอลัมน์ของคุณ เมื่อทำเช่นนั้นคุณจะส่งผ่านจาก 0.205 ถึง 0.180 สำหรับ 2,000 คำขอ 30 แถวต่อแถว
user103307
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.