Замыкания в PHP: анонимные и стрелочные функции (use, примеры и лучшие практики)
Поисковый запрос, под который оптимизирована статья: «Замыкания в PHP» и «Анонимные и стрелочные функции в PHP». Если вы хотите писать компактный и выразительный код, замыкания (closures) — то, что нужно. Разберёмся на понятных примерах, когда выбирать анонимные функции, а когда — стрелочные, как работает use, в чём разница между захватом по значению и по ссылке, и какие ошибки встречаются чаще всего.
Что такое замыкание в PHP
Замыкание — это функция, которая «замыкает» (захватывает) переменные из внешней области видимости. В PHP это анонимные функции (Closure) и стрелочные функции (fn), появившиеся в PHP 7.4.
$greet = function (string $name): string {
return "Привет, $name!";
};
echo $greet('Алиса'); // Привет, Алиса!
Оператор use: захват переменных
По умолчанию анонимная функция не видит переменные из внешней области. Чтобы «принести» их внутрь, используют use.
$prefix = 'ID-';
$makeId = function (int $n) use ($prefix): string {
return $prefix . str_pad((string)$n, 5, '0', STR_PAD_LEFT);
};
echo $makeId(42); // ID-00042
Важно: по умолчанию use копирует переменную по значению. Изменение внутри функции не повлияет на внешнюю.
$x = 10;
$fn = function () use ($x) {
$x++;
echo $x; // 11
};
$fn();
echo $x; // 10 (внешняя переменная не изменилась)
Захват по ссылке
Если нужно изменить внешнюю переменную, захватывайте по ссылке через &.
$count = 0;
$inc = function () use (&$count) {
$count++;
};
$inc();
$inc();
echo $count; // 2
Стрелочные функции (fn) и чем они отличаются
Стрелочные функции — это короткий синтаксис для простых выражений. Они автоматически захватывают переменные по значению (как будто с use), но не поддерживают многострочные тела и нельзя сделать захват по ссылке.
$factor = 10;
$mul = fn(int $n): int => $n * $factor; // $factor уже доступен, use не нужен
echo $mul(5); // 50
Если нужно мутировать внешнюю переменную — используйте обычную анонимную функцию с use (&$var).
Практика: колбэки для массивов
Замыкания отлично подходят для array_map, array_filter, usort и т. п.
$nums = [1, 2, 3, 4, 5];
$k = 3;
$scaled = array_map(fn($n) => $n * $k, $nums); // [3, 6, 9, 12, 15]
$words = ['php', 'Laravel', 'symfony', 'CodeIgniter'];
$onlyLower = array_filter($words, fn($w) => $w === strtolower($w)); // ['php']
$users = [
['name' => 'Ann', 'age' => 19],
['name' => 'Bob', 'age' => 25],
['name' => 'Eve', 'age' => 21],
];
usort($users, fn($a, $b) => $a['age'] $b['age']);
// Теперь по возрастанию возраста
Фабрики и замыкания: параметризация поведения
Замыкание удобно возвращать из функции, чтобы сконструировать «на лету» поведение с параметрами.
function makeValidator(int $min, int $max): Closure {
return function (int $n) use ($min, $max): bool {
return $n >= $min && $n <= $max;
};
}
$ageValidator = makeValidator(18, 30);
var_dump($ageValidator(21)); // true
var_dump($ageValidator(31)); // false
Кеширование результатов (мемоизация) с замыканиями
Иногда функция часто вызывается с одними и теми же аргументами. Замыкание позволяет легко добавить кеш.
function memoize(callable $fn): Closure {
$cache = [];
return function (...$args) use ($fn, &$cache) {
$key = md5(serialize($args));
if (!array_key_exists($key, $cache)) {
$cache[$key] = $fn(...$args);
}
return $cache[$key];
};
}
$slowFib = function (int $n) use (&$slowFib): int {
return $n < 2 ? $n : $slowFib($n - 1) + $slowFib($n - 2);
};
$fib = memoize($slowFib);
echo $fib(35); // значительно быстрее при повторных вызовах
Замыкания и $this: привязка контекста
Внутри метода анонимная функция видит $this. Но можно жёстко отвязать контекст, объявив функцию как static — тогда $this внутри недоступен.
class Repo {
private array $items = [1, 2, 3];
public function each(callable $fn): void {
foreach ($this->items as $i) {
$fn($i); // внутри колбэка доступен $this, если он не static
}
}
}
$r = new Repo();
$r->each(function ($i) {
echo $this instanceof Repo ? "ok\n" : "no\n"; // ok
});
$r->each(static function ($i) {
echo isset($this) ? 'есть this' : 'нет this'; // нет this
});
Типы: callable vs Closure
callable — любой вызваемый тип (имя функции, [объект, метод], замыкание и т. п.). Closure — именно объект анонимной функции. Если функция должна принимать только замыкание — указывайте Closure.
function runTwice(Closure $job): void {
$job();
$job();
}
runTwice(function () { echo 'Hi '; }); // Hi Hi
Подводные камни и частые ошибки
- Забытый
use. Анонимная функция не видит внешние переменные безuse(кроме стрелочных функций). - Нужна мутация — захватывайте по ссылке:
use (&$var). - Стрелочные функции — только одно выражение. Нужна логика в несколько строк — используйте обычную.
- Сериализация:
Closureпо умолчанию не сериализуется. Не кладите замыкания в сессию/кеш как данные. - Производительность: не создавайте замыкания в тесных циклах без необходимости — вынесите наружу или переиспользуйте.
Реальный пример: динамическая валидация формы
Допустим, требуется гибкая валидация нескольких полей. Замыкания позволяют описать правила декларативно.
$rules = [
'email' => function (string $v): bool { return $v !== '' && str_contains($v, '@'); },
'age' => function (string $v): bool { $n = (int)$v; return $n >= 18 && $n <= 65; },
];
function validate(array $input, array $rules): array {
$errors = [];
foreach ($rules as $field => $rule) {
$value = $input[$field] ?? '';
if (!$rule($value)) {
$errors[$field] = 'Некорректное значение';
}
}
return $errors;
}
$input = ['email' => 'user@example.com', 'age' => '20'];
$errors = validate($input, $rules);
var_dump($errors); // []
Лучшие практики
- Старайтесь делать колбэки чистыми (без побочных эффектов), когда это возможно.
- Для коротких преобразований используйте стрелочные функции — это компактно и читаемо.
- Для сложной логики и мутаций выбирайте обычные анонимные функции с
use. - Явно типизируйте аргументы и возвращаемые значения — ошибки ловятся раньше.
- Повторно используйте замыкания: сохраняйте в переменные, передавайте в функции высшего порядка.
Итоги
Замыкания — фундаментальный инструмент PHP, позволяющий писать выразительный и модульный код. Освойте use, разницу между анонимными и стрелочными функциями, и вы заметите, как колбэки в массивах, валидация, фабрики и кеширование станут проще.
Хотите системно прокачать PHP и базу данных с практикой? Рекомендую посмотреть программу и начать обучение на курсе «PHP и MySQL с Нуля до Гуру 3.0 — запишитесь и начните сейчас».
-
Создано 18.02.2026 17:01:24
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.