Внешние переменные use ($var)
Glossary overview

Внешние переменные use ($var)

В PHP конструкция use($var) используется для передачи внешних переменных во внутреннюю область видимости анонимной функции (closure).

Вот простой пример, который всё объяснит:

$name = 'John';

$sayHello = function() use ($name) {
    echo "Hello, $name!";
};

$sayHello(); // Выведет: Hello, John!

Зачем нужен use ($var)?

Анонимные функции (замыкания) не имеют доступа к переменным из внешней области по умолчанию. Чтобы “захватить” переменные извне, мы используем use.

Передача по значению и по ссылке

  • По умолчанию use ($var) передаёт переменные по значению (копия):
$count = 0;

$increment = function() use ($count) {
    $count++;
    echo $count;
};

$increment(); // 1
echo $count;  // 0 — оригинальная переменная не изменилась
  • Чтобы передать по ссылке, используем &:
$count = 0;

$increment = function() use (&$count) {
    $count++;
};

$increment();
echo $count; // 1 — переменная изменилась

Почему нельзя просто передать переменную в функцию как аргумент?

На самом деле, можно и часто лучше передавать переменные через аргументы, если это возможно. Но use($var) нужен именно в тех случаях, когда:

1. Ты используешь анонимную функцию (closure) как callback

И ты не можешь напрямую передать аргументы, потому что эту функцию вызывает другая часть кода.

Пример с array_map:

$prefix = 'Item: ';
$items = ['apple', 'banana', 'cherry'];

$result = array_map(function($item) use ($prefix) {
    return $prefix . $item;
}, $items);

print_r($result);

Здесь array_map вызывает нашу функцию с аргументом $item. Мы не можем передать $prefix напрямую как аргумент, но хотим использовать его — поэтому use.

2. Ты определяешь функцию “на лету” и хочешь использовать внешние переменные

Например, при создании замыканий внутри циклов или для событий.

Пример с циклами:

$callbacks = [];

for ($i = 1; $i <= 3; $i++) {
    $callbacks[] = function() use ($i) {
        echo $i . PHP_EOL;
    };
}

foreach ($callbacks as $callback) {
    $callback(); // выведет 1, 2, 3
}

3. Ты хочешь сохранить “снимок” переменной на момент создания функции

Если бы ты передавал переменную по ссылке или без use, её значение могло бы измениться к моменту вызова.

Сравнение:

Вот наглядное сравнение одного и того же функционала — с передачей переменной через аргумент и через use.

Вариант 1: Через аргумент (прямой способ)

function greet($name) {
    echo "Hello, $name!";
}

greet('Alice'); // Hello, Alice!

Тут всё просто: переменная $name передаётся как аргумент функции. Это классика.

Вариант 2: Через use (например, с анонимной функцией)

$name = 'Alice';

$greet = function() use ($name) {
    echo "Hello, $name!";
};

$greet(); // Hello, Alice!

Здесь мы определили анонимную функцию, которая “захватила” переменную $name из внешней области с помощью use.

Вот пример с замыканием внутри цикла, который показывает, зачем нужен use, и как он “захватывает” переменную.

Без use (не работает как ожидается):

$callbacks = [];

for ($i = 1; $i <= 3; $i++) {
    $callbacks[] = function() {
        echo $i . PHP_EOL;
    };
}

foreach ($callbacks as $callback) {
    $callback(); // ❌ Ошибка: Undefined variable $i
}

Тут ошибка, потому что $i не видна внутри функции. Она не захвачена, и PHP не знает о ней.

С use (замыкание работает):

$callbacks = [];

for ($i = 1; $i <= 3; $i++) {
    $callbacks[] = function() use ($i) {
        echo $i . PHP_EOL;
    };
}

foreach ($callbacks as $callback) {
    $callback();
}

/
1
2
3

Каждая функция “захватывает” текущее значение $i на момент создания — именно это и называется замыкание (closure).

Что происходит?

Когда мы пишем function() use ($i), PHP создаёт копию переменной $i в момент, когда функция создаётся, и сохраняет её внутри самой функции.

А теперь — пример с ссылкой:

$callbacks = [];

for ($i = 1; $i <= 3; $i++) {
    $callbacks[] = function() use (&$i) {
        echo $i . PHP_EOL;
    };
}

foreach ($callbacks as $callback) {
    $callback();
}

// Вывод
4
4
4

Почему? Потому что мы передаём $i по ссылке, и к моменту вызова функции $i = 4 (после завершения цикла). Все функции используют одну и ту же переменную.

Итого

ПодходКогда использовать
Через аргументыВсегда, когда можешь. Это понятнее и контролируемее
Через useКогда невозможно передать как аргумент (внутри callback, замыкания и т.п.)