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


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.