Промежуточное программное обеспечение маршрута

Flight поддерживает промежуточное программное обеспечение маршрута и группы маршрутов. Промежуточное программное обеспечение - это функция, которая выполняется до (или после) обратного вызова маршрута. Это отличный способ добавить проверки аутентификации API в ваш код или проверить, имеет ли пользователь разрешение на доступ к маршруту.

Основное промежуточное программное обеспечение

Вот простой пример:

// Если вы предоставляете только безымянную функцию, она будет выполнена перед обратным вызовом маршрута. 
// нет "после" промежуточных функций, за исключением классов (см. ниже)
Flight::route('/path', function() { echo ' Вот я!'; })->addMiddleware(function() {
    echo 'Сначала промежуточное программное обеспечение!';
});

Flight::start();

// Это выведет "Сначала промежуточное программное обеспечение! Вот я!"

Существуют некоторые очень важные заметки о промежуточном программном обеспечении, о которых вам следует знать перед тем, как использовать их:

  • Промежуточные функции выполняются в порядке их добавления к маршруту. Выполнение аналогично тому, как это делает Slim Framework.
    • 'before' выполняются в порядке добавления, 'after' выполняются в обратном порядке.
  • Если ваша функция промежуточного программного обеспечения возвращает false, вся работа останавливается и генерируется ошибка 403 Forbidden. Вероятно, вам захочется об этом более гармонично позаботиться с помощью Flight::redirect() или чего-то подобного.
  • Если вам нужны параметры из вашего маршрута, они будут переданы в виде одного массива в вашу функцию промежуточного программного обеспечения (function($params) { ... } или public function before($params) {}). Причина в том, что вы можете структурировать параметры в группы, и в некоторых из этих групп ваши параметры могут фактически появиться в другом порядке, что нарушило бы функцию промежуточного программного обеспечения, обращаясь к неправильному параметру. Таким образом, вы можете обращаться к ним по имени, а не по позиции.
  • Если вы передаете только имя промежуточного программного обеспечения, оно будет автоматически выполнено контейнером внедрения зависимостей и промежуточное программное обеспечение будет выполнено с необходимыми параметрами. Если у вас не зарегистрирован контейнер внедрения зависимостей, он передаст в __construct() экземпляр flight\Engine.

Классы промежуточного программного обеспечения

Промежуточное программное обеспечение можно зарегистрировать также как класс. Если вам нужна функциональность "после", вы должны использовать класс.

class MyMiddleware {
    public function before($params) {
        echo 'Сначала промежуточное программное обеспечение!';
    }

    public function after($params) {
        echo 'Последнее промежуточное программное обеспечение!';
    }
}

$MyMiddleware = new MyMiddleware();
Flight::route('/path', function() { echo ' Вот я! '; })->addMiddleware($MyMiddleware); // также ->addMiddleware([ $MyMiddleware, $MyMiddleware2 ]);

Flight::start();

// Это выведет "Сначала промежуточное программное обеспечение! Вот я! Последнее промежуточное программное обеспечение!"

Обработка ошибок промежуточного программного обеспечения

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

  1. Вы можете вернуть false из функции промежуточного программного обеспечения, и Flight автоматически вернет ошибку 403 Forbidden, но без настроек.
  2. Вы можете перенаправить пользователя на страницу входа, используя Flight::redirect().
  3. Вы можете создать пользовательскую ошибку в промежуточном программном обеспечении и остановить выполнение маршрута.

Простой пример

Вот простой пример с возвратом false:

class MyMiddleware {
    public function before($params) {
        if (isset($_SESSION['user']) === false) {
            return false;
        }

        // поскольку это верно, всё продолжает идти
    }
}

Пример перенаправления

Вот пример перенаправления пользователя на страницу входа:

class MyMiddleware {
    public function before($params) {
        if (isset($_SESSION['user']) === false) {
            Flight::redirect('/login');
            exit;
        }
    }
}

Пример пользовательской ошибки

Предположим, вам нужно сгенерировать JSON-ошибку, потому что вы создаете API. Вы можете сделать это следующим образом:

class MyMiddleware {
    public function before($params) {
        $authorization = Flight::request()->headers['Authorization'];
        if(empty($authorization)) {
            Flight::jsonHalt(['error' => 'Необходимо войти в систему, чтобы получить доступ к этой странице.'], 403);
            // или
            Flight::json(['error' => 'Необходимо войти в систему, чтобы получить доступ к этой странице.'], 403);
            exit;
            // или
            Flight::halt(403, json_encode(['error' => 'Необходимо войти в систему, чтобы получить доступ к этой странице.']);
        }
    }
}

Группирование промежуточного программного обеспечения

Вы можете добавить группу маршрутов, и затем у каждого маршрута в этой группе будет также применяться то же промежуточное программное обеспечение. Это полезно, если вам нужно сгруппировать несколько маршрутов, например при помощи промежуточного программного обеспечения аутентификации для проверки ключа API в заголовке.


// добавлено в конце метода группы
Flight::group('/api', function() {

    // Этот "пустой" маршрут на самом деле совпадет с /api
    Flight::route('', function() { echo 'api'; }, false, 'api');
    // Это совпадет с /api/users
    Flight::route('/users', function() { echo 'users'; }, false, 'users');
    // Это совпадет с /api/users/1234
    Flight::route('/users/@id', function($id) { echo 'пользователь:'.$id; }, false, 'user_view');
}, [ new ApiAuthMiddleware() ]);

Если вы хотите применить глобальное промежуточное программное обеспечение ко всем вашим маршрутам, вы можете добавить "пустую" группу:


// добавлено в конце метода группы
Flight::group('', function() {

    // Это все еще /users
    Flight::route('/users', function() { echo 'users'; }, false, 'users');
    // А это все еще /users/1234
    Flight::route('/users/@id', function($id) { echo 'пользователь:'.$id; }, false, 'user_view');
}, [ new ApiAuthMiddleware() ]);