Middleware in Leaf MVC
Middleware is a piece of code that runs before or after your application processes a request. It helps control the flow of requests and responses. For example, when a user visits a page on your app, you can use middleware can check if the user is logged in and if everything is okay, the request moves on to the next step; if not, the middleware can redirect the user.
Before writing custom middleware, check out Leaf Modules—they offer built-in functionality that might already cover your needs, saving you time and effort.
Creating Middleware
In Leaf MVC, middleware are just classes that extend the Leaf\Middleware
class. Here's an example of a middleware that logs the request method and URI:
<?php
namespace App\Middleware;
use Leaf\Middleware;
class LogRequestMiddleware extends Middleware
{
public function call()
{
$method = request()->method();
$uri = request()->uri();
echo "[$method] $uri\n";
}
}
Of course, you don't have to do this manually. You can use the MVC Console to generate a middleware for you:
php leaf g:middleware LogRequest
This will generate a LogRequestMiddleware.php
file in the app/middleware
folder.
Loading Middleware for all routes
Once you generate your middleware, you can choose to load it for all routes in your application. This means that the middleware will run for every request made to your application, regardless of the route. It could be useful for logging requests, checking if a user is authenticated, etc.
To do this, you need to add the middleware to the app/routes/index.php
file. We have added an example middleware to the file for you:
use App\Middleware\LogRequestMiddleware;
...
/*
|--------------------------------------------------------
| Set middleware for all routes
|--------------------------------------------------------
|
| You can use app()->use() to load middleware for all
| routes in your application.
|
*/
app()->use(LogRequestMiddleware::class);
app()->use(AnotherMiddleware::class);
Loading Middleware for specific routes
The most common use case for middleware is to load it for specific routes, instead of all routes. You can do this by adding the middleware to the particular route you want to use it in using route parameters.
<?php
use App\Middleware\LogRequestMiddleware;
...
app()->get('/my-route', [
'middleware' => LogRequestMiddleware::class,
'MyController@index'
]);
This will run the LogRequestMiddleware
middleware only for the /my-route
route.
Passing data from middleware
You can pass data from middleware to your route handler using response()->next()
, making it available in your controller or another middleware.
<?php
namespace App\Middleware;
use Leaf\Middleware;
class LogRequestMiddleware extends Middleware
{
public function call($next)
{
$method = request()->method();
$uri = request()->uri();
echo "[$method] $uri\n";
response()->next('You can pass any value');
}
}
This uses Leaf's Response object to output data from the middleware that can only be accessed by your next handler (hence the name next
). You can access that data in your route handler using the request()->next()
method.
<?php
namespace App\Controllers;
class MyController extends Controller
{
public function index()
{
$middlewareData = request()->next();
echo $middlewareData; // will output "You can pass any value"
}
}
Once the data is read using request()->next()
, it is removed from the request object and cannot be accessed again during the request lifecycle.
Controller Middleware New
The middleware we have seen so far is applied to routes, which is great for most use-cases. However, there are times when you may want to apply middleware to one or more controller methods, instead of individual routes. This is especially useful when you have an application which has both web and API routes, and you want to apply different middleware to each. To use this, find the controller you want to add middleware to, and add a __middleware
method to it:
<?php
namespace App\Controllers\Mobile;
/**
* This is a base controller for the mobile namespace
*/
class Controller extends \App\Controllers\Controller
{
public function __middleware()
{
auth()->config('session', false);
if (!auth()->user()) {
response()->json([
'success' => false,
'message' => 'Unauthorized',
], 401);
return false;
}
return true;
}
}
In this example, we have a base controller for the Mobile
namespace, which contains all controllers for our mobile API. The __middleware
method disables session auth, meaning all authentication will be done using API tokens (JWTs), and then returns a JSON response if the user is not authenticated. Since this is a base controller, all controllers in the Mobile
namespace will inherit this middleware which means all routes in this namespace will require authentication.
Unlike the route middleware, the controller middleware returns a boolean value. If it returns true
, the request will continue to the next step (either another middleware or the controller method). If it returns false
, the request will stop and no further processing will be done.
What to read next
Middleware is a powerful tool that can help you control the flow of requests in your application, but Leaf already has a lot of functionality built-in that you might not need to write your own middleware for. Check out some of the other features of Leaf & Leaf MVC:
Authentication
Learn more about routing in Leaf MVC, dynamic routes, middleware and more.
Roles & Permissions
Learn how to process incoming requests, handle form submissions, and more.
Session Data
Save user data, flash messages, and more using Leaf's session module.
Frontend
Learn about SSR, SPA, and how to use Leaf with your favorite frontend framework.