Доступ до зовнішньої змінної, використовуючи анонімну функцію як парами


93

В основному я використовую цю зручну функцію для обробки 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']у вар (це лише приклад).

Як я міг це зробити? Я думав щось подібне, але це не дуже елегантно:

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

echo $result;

Відповіді:


188

Ви повинні використовувати, 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
Оскільки екземпляри класу завжди передаються за посиланням, вам не потрібно використовувати & для них. (якщо ви повністю не перезаписали екземпляр).
Джоел Харкес

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 на 2000 запитів по 30 рядків кожен.
user103307
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.