Flight supports route and group route middleware. Middleware is a function that is executed before (or after) the route callback. This is a great way to add API authentication checks in your code, or to validate that the user has permission to access the route.
Here's a basic example:
// If you only supply an anonymous function, it will be executed before the route callback. // there are no "after" middleware functions except for classes (see below) Flight::route('/path', function() { echo ' Here I am!'; })->addMiddleware(function() { echo 'Middleware first!'; }); Flight::start(); // This will output "Middleware first! Here I am!"
There are some very important notes about middleware that you should be aware of before you use them:
Flight::redirect()
function($params) { ... }
public function before($params) {}
flight\Engine
__construct()
Middleware can be registered as a class as well. If you need the "after" functionality, you must use a class.
class MyMiddleware { public function before($params) { echo 'Middleware first!'; } public function after($params) { echo 'Middleware last!'; } } $MyMiddleware = new MyMiddleware(); Flight::route('/path', function() { echo ' Here I am! '; })->addMiddleware($MyMiddleware); // also ->addMiddleware([ $MyMiddleware, $MyMiddleware2 ]); Flight::start(); // This will display "Middleware first! Here I am! Middleware last!"
Let's say you have an auth middleware and you want to redirect the user to a login page if they are not authenticated. You have a couple of options at your disposal:
Here is a simple return false; example:
class MyMiddleware { public function before($params) { if (isset($_SESSION['user']) === false) { return false; } // since it's true, everything just keeps on going } }
Here is an example of redirecting the user to a login page:
class MyMiddleware { public function before($params) { if (isset($_SESSION['user']) === false) { Flight::redirect('/login'); exit; } } }
Let's say you need to throw a JSON error because you're building an API. You can do that like this:
class MyMiddleware { public function before($params) { $authorization = Flight::request()->headers['Authorization']; if(empty($authorization)) { Flight::jsonHalt(['error' => 'You must be logged in to access this page.'], 403); // or Flight::json(['error' => 'You must be logged in to access this page.'], 403); exit; // or Flight::halt(403, json_encode(['error' => 'You must be logged in to access this page.']); } } }
You can add a route group, and then every route in that group will have the same middleware as well. This is useful if you need to group a bunch of routes by say an Auth middleware to check the API key in the header.
// added at the end of the group method Flight::group('/api', function() { // This "empty" looking route will actually match /api Flight::route('', function() { echo 'api'; }, false, 'api'); // This will match /api/users Flight::route('/users', function() { echo 'users'; }, false, 'users'); // This will match /api/users/1234 Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); }, [ new ApiAuthMiddleware() ]);
If you want to apply a global middleware to all your routes, you can add an "empty" group:
// added at the end of the group method Flight::group('', function() { // This is still /users Flight::route('/users', function() { echo 'users'; }, false, 'users'); // And this is still /users/1234 Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); }, [ new ApiAuthMiddleware() ]);