Основная идея использования замыканий - передача в определенный метод/функцию (обертку) части кода, который будет выполняться внутри этого метода с возможностью использования для своей работы как свойства данного класса, в который передается, так и локальные переменные из окружения где объявлена эта анонимная функция (замыкание).
В этой заметке, я хочу предоставить еще один пример использования замыкания, т.к. в сети их довольно мало. Особое внимание уделено анонимной функции, с помощью которой и делается замыкание. Реализуем передачу в нее параметров из разных областей видимости для выполнение определенных задач.

В качестве примера - 2 класса, упрощенно демонстрирующих соединение пользователей с базой данных.
Class User {

    private $name, $pas;
    static public $countConnect = 0;
    public $host = 'localhost';
    public $dbname = 'test';

    function __construct($name, $pas) {
        $this->name = $name;
        $this->pas = $pas;

        $db = new Db();
        $db->check($this->name, $this->pas, $this->fallback());
    }
    
    function get($text) {
        echo $text;
    }
    function fallback() {
        $host = $this->host;
        $dbname = $this->dbname;
        $countConnect = self::$countConnect;

        $fallback = function($start) use ($host, $dbname, $countConnect) {
            $this->get($start);
            self::$countConnect++;
            return ['host' => $host, 'dbname' => $dbname, 'countConnect' => $countConnect];
        };
    return $fallback;
    }
}

class Db {
    const GO = 'Старт!.. ';

    function connect($name, $config) {
        echo 'Соединяю пользователя ' . $name;
        echo ' ' . $config['countConnect'] . '... ';
        echo 'Настройки: ' . $config['host'] . ', ' . $config['dbname'];
        echo '<br>';
    }

    function check($name, $pas, Closure $fallback) {
        if ($name != 'admin' || $pas != '123') {
            echo 'Неверный логин или пароль.<br>';
            return false;
        }
        $config = $fallback(self::GO); // отложенное выполнение кода. Результат сохраняем 
        $this->connect($name, $config); //результат выполнения (массив)передаем
    }
}

$user1 = new User('admin', 123);
$user1 = new User('admin', 555);
$user1 = new User('admin', 123);
$user1 = new User('admin', 123);
Результат выполнения этого кода:
Старт!.. Соединяю пользователя admin 0... Настройки: localhost, test
Неверный логин или пароль.
Старт!.. Соединяю пользователя admin 1... Настройки: localhost, test
Старт!.. Соединяю пользователя admin 2... Настройки: localhost, test
Проверку логина и пароля я сделал просто для большей правдоподобности примера.



Итак, для соединения с базой данных, создается новый объект - экземпляр класса User, в конструктор которого пользователь передает свои данные (логин и пароль). Данный класс так же хранит настройки для входа в БД по-умолчанию:
public $host = 'localhost';
public $dbname = 'test';

и используется счетчик успешных соединений с БД.

Сохранив в свойствах класса данные пользователя, конструктор создает объект класса Db, который и производит соединение с БД. В данном классе реализована проверка логина и пароля, но в него не передаются дополнительные параметры, такие как хост и название базы данных. Это реализовано с помощью анонимной функции.
Вместе с данными пользователя, в метод check() класса Db так же передается наша анонимная функция:
$this->fallback()
которую возвращает метод fallback().
Анонимные функции c PHP5.3 являются экземплярами класса Closure, поэтому при приеме аргумента, можем ограничить его тип:
function check($name, $pas, Closure $fallback) { ...

До сих пор данная функция не вызывалась и только строкой
$config = $fallback(self::GO);
выполняем ее.

Тут следует обратить внимание на аргументы, которая она получает для своей работы. Эта анонимная функция выполняется в области видимости класса Db, поэтому мы легко передаем ей нужные данные в качестве аргуметов. В данном примере это константа "GO". Исходный класс, где она была объявлена не содержал такого параметра, поэтому мы предусмотрели его заранее. Кроме того, анонимная функция может получать доступ к данным из той области видимости, где она была объявлена - метод fallback() класса User с помощью оператора "use":
$fallback = function($start) use ($host, $dbname, $countConnect) {
      $this->get($start);
      self::$countConnect++;
      return ['host' => $host, 'dbname' => $dbname, 'countConnect' => $countConnect];
};
Тут и проявляется механизм замыканий в PHP.

Также, внутри функции, мы имеем доступ к свойствам и методам класса в котором она объявлена - в примере мы увеличиваем значение статического свойства на единицу при каждом соединении пользователя:
self::$countConnect++;
Но мы могли сделать по-другому, используя передачу параметров в функцию по ссылке (для возможности изменения). В таком случае, метод мог бы выглядеть так:
function fallback() {
    $host = $this->host;
    $dbname = $this->dbname;
    static $countConnect = 0;

    $fallback = function($start) use ($host, $dbname, &$countConnect) {
        $this->get($start);
        $countConnect++;
        return ['host' => $host, 'dbname' => $dbname, 'countConnect' => $countConnect];
    };
    return $fallback;
}
создаем статическую переменную (принадлежащую классу, а не объекту, что позволяет сохранять свое значение при создании каждого нового экземпляра класса) $countConnect и при каждом следующем вызове анонимной функции увеличиваем ее значение на единицу.
Для примера, я показал передачу (и вывод в виде сообщения) аргумента функции из класса Db, а именно $start, которая, тем не менее, за счет анонимной функции появляется и используется в контексте класса User:
$this->get($start);

Так же, как я писал выше, анонимная функция у нас ответственна за передачу дополнительных параметров соединения с базой данных в класс Db. Поэтому она возвращает нужные данные:
return ['host' => $host, 'dbname' => $dbname, 'countConnect' => $countConnect];
которые сохраняются в переменную $config и передаются в метод устанавливающий соединение с БД:
$config = $fallback(self::GO);
$this->connect($name, $config);


Вот и все, применение замыканиям можно найти в самых разных случаях. Главное научиться ими пользоваться.