Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Замыкание PHP: Функции

Каждая функция в своем теле задает так называемую область видимости. Внутри этой области доступны только те переменные, которые были определены там же. Определенные вне функции переменные невидимы внутри нее:

<?php

$age = 5;

function generate()
{
    print_r($age);
}

generate();

Этот код выдаст предупреждение PHP Notice: Undefined variable: age. Переменная $age определена вне контекста функции и невидима внутри. Точно такое же поведение и у анонимных функций:

<?php

$age = 5;

$generate = function () {
    print_r($age);
};

$generate(); // PHP Notice:  Undefined variable: age

Но передача аргументов все же возможна, и делается она благодаря замыканию. С помощью этого механизма можно захватить переменные из внешнего окружения и использовать их внутри. Правда, это работает только для анонимных функций. Замыканием нередко называют и саму функцию, которая осуществила захват внешних переменных:

<?php

$age = 5;

$generate = function () use ($age) {
    print_r($age);
};

$generate(); // 5

Захват переменных осуществляется с помощью ключевого слова use и списка переменных, который идет после этого слова. Крайне важно осознать, что use используется при определении функции, а не ее вызове.

Может возникнуть закономерный вопрос: «Зачем это делать, если переменные можно передать в сам вызов?». Попробуем разобраться:

<?php

$age = 5;

$generate = function ($age) {
    print_r($age);
};

$generate($age); // 5

Замыкания полезны, когда функция определяется в одном месте, а используется в совершенно другом. Замыкание позволяет не таскать за собой гору переменных, а в некоторых ситуациях без него просто не обойтись.

Вспомните функцию without() из пакета Funct. Она принимает на вход массив и значение, а возвращает новый массив, полученный фильтрацией старого по переданному значению. Его реализация построена на функциях высшего порядка и подразумевает фильтрацию. Сложность возникает при описании предиката, ведь внутри анонимной функции нужно сравнивать текущее значение и переданный элемент. Замыкание позволяет решить эту задачу просто:

<?php

function without(array $items, $value)
{
    $filtered = array_filter($items, function ($item) use ($value) {
        return $item !== $value;
    });
    // Сбрасываем ключи
    return array_values($filtered);
}

without([3, 4, 10, 4, 'true'], 4); // [3, 10, 'true']

Без добавления use ($value) ничего не получится, потому что $value не виден внутри анонимной функции.

В замыкание можно передать данные по ссылке, что позволит их менять внутри. Но делать так никогда не стоит. Подобное использование создает невероятно сложный в отладке и сопровождении код. Единственная причина, по которой можно использовать передачу по ссылке - рекурсия внутри анонимной функции. Подробнее об этом в другом курсе.

Стрелочные функции

Главная цель введения стрелочных функций — это создание более лаконичного кода. Поэтому кроме сокращенного синтаксиса, они получили автоматический захват внешних переменных. Другими словами, при использовании стрелочных функций нам не нужен use:

<?php

$age = 5;

$generate = fn() => print_r($age);

$generate(); // 5

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Laravel
10 месяцев
с нуля
Старт 2 мая

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»