В 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, замыкания и т.п.) |
