Middleware
Lumberjack supports PSR-15/7 Middleware. Middleware can be added via the Router to individual routes or route groups or via WordPress Controllers.
At it's simplest, adding Middleware to a route can be done by passing an object to the
middleware()
function:$middleware = new AddHeaderMiddleware('X-Key1', 'abc');
Router::get('route/uri', '\MyNamespace\TestController@testMethod')->middleware($middleware);
Multiple middleware can be added by passing more params to the
middleware()
function:$header = new AddHeaderMiddleware('X-Key1', 'abc');
$auth = new AuthMiddleware();
Router::get('route/uri', '\MyNamespace\TestController@testMethod')->middleware($header, $auth);
Or alternatively, you can also pass an array of middleware:
$header = new AddHeaderMiddleware('X-Key1', 'abc');
$auth = new AuthMiddleware();
Router::get('route/uri', '\MyNamespace\TestController@testMethod')->middleware([$header, $auth]);
Middleware can also be added to a group. To do so you need to pass an array as the first parameter of the
group()
function instead of a string.$header = new AddHeaderMiddleware('X-Key1', 'abc');
Router::group(['prefix' => 'my-prefix', 'middleware' => $header]), function ($group) {
$group->get('route1', function () {}); // GET `/my-prefix/route1`
$group->get('route2', function () {}); // GET `/my-prefix/route2`
});
You can also pass an array of middleware if you need more than one:
$header = new AddHeaderMiddleware('X-Key1', 'abc');
$auth = new AuthMiddleware();
Router::group(['prefix' => 'my-prefix', 'middleware' => [$header, $auth]]), function ($group) {
$group->get('route1', function () {}); // GET `/my-prefix/route1`
$group->:get('route2', function () {}); // GET `/my-prefix/route2`
});
You can also apply Middleware on a Controller class too, either for use with the Router or as a WordPress Controller. In order to do this your Controller must extend the
App\Http\Controllers\Controller
base class.Middleware is added by calling the
middleware()
function in your Controller's __constructor()
.use App\Http\Controllers\Controller;
class MyController extends Controller
{
public function __construct()
{
// Add one at a time
$this->middleware(new AddHeaderMiddleware('X-Key1', 'abc'));
$this->middleware(new AuthMiddleware());
// Add multiple with one method call
$this->middleware([
new AddHeaderMiddleware('X-Key1', 'abc',
new AuthMiddleware(),
]);
}
}
By default all Middleware added via a Controller will affect all methods on that class. To limit what methods Middleware applies to you can use
only()
and except()
:use App\Http\Controllers\Controller;
class MyController extends Controller
{
public function __construct()
{
// Only apply to `send()` method
$this->middleware(new AddHeaderMiddleware('X-Key1', 'abc'))->only('send');
// Apply to all methods except `show()` method
$this->middleware(new AuthMiddleware())->except('show');
// Multiple methods can be provided in an array to both methods
$this->middleware(new AuthMiddleware())->except(['send', 'show']);
}
}
Available in
v4.3.0
and aboveCreating new instances of middleware in your routes or controllers can have a couple of negative outcomes:
- 1.The objects are instantiated and take up memory whether they're used or not
- 2.Your route definitions can become less readable
These issues can both be addressed using Middleware Aliases. Instead of creating instances in your code, you register a string alias that can be used instead.
To register an alias you can use the
MiddlewareAliases
facade. It is recommended that you use this in the boot()
method of the AppServiceProvider
class.There are 3 ways to define your middleware alias:
- A closure factory (recommended - always creates a new instance when used)
- A class name (always resolves a new instance from the Container when used)
- A previously instantiated object (you don't get the benefits of lazy loading)
See "Setting entries in the container" for more information about the differences between these. While only the class name uses the container, principally they behave in the same way with regards to lazy-loading and object instantiation.
It is recommended that the alias is registered using a closure that acts as a factory, like so:
namespace App\Providers;
use Rareloop\Lumberjack\Facades\MiddlewareAliases;
class AppServiceProvider
{
function boot()
{
// Create from closure factory
MiddlewareAliases::set('auth', function() {
return new AuthMiddleware;
});
}
}
// Create from class name
MiddlewareAliases::set('cors', \My\Middleware\Cors::class);
// Or
MiddlewareAliases::set('cors', '\My\Middleware\Cors');
When using this method, you do not get the benefits of lazy loading. i.e. The object will be created whether or not it is needed for the current request.
// Create from existing object
MiddlewareAliases::set('addheader', new \My\Middleware\AddHeader());
Middleware Aliases can be used anywhere middleware can normally be used, both in the Router and through Controllers.
If, for example, an Alias had been registered for an
AuthMiddleware
with the key auth
like so:MiddlewareAliases::set('auth', function() {
return new AuthMiddleware;
});
You could use this in your route definition like this:
Router::get(
'route/uri',
'\App\Http\Controllers\TestController@testMethod'
)->middleware('auth');
You can register Middleware Aliases which accept parameters. It is advised if you're doing this to use the Closure Factory registration technique.
// Register in AppServiceProvider::boot()
MiddlewareAliases::set('addheader', function($key, $value) {
return new AddHeader($key, $value);
});
// Use in routes.php
Router::get(
'hello-world',
'MyController@hello'
)->middleware('addheader:X-Key:HeaderValue');
In this example,
$key
will have the value X-Key
and $value
will have the value of HeaderValue
.While you can use any PSR 15/7 Middleware, sometimes you need to write your own. In this example, we will create custom middleware that adds the response header
X-Foo
.
First, create the class in app/Http/Middleware/ExampleMiddleware.php
(create the folder if it doesn't exist) with the following content:<?php
namespace App\Http\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ExampleMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$response = $handler->handle($request);
return $response;
}
}
In our example, we want to modify the response. Below we add the
X-Foo
header to the response:return $response->withHeader('X-Foo', 'Bar');
If you need to modify the request before it gets passed to your application, you can do so before
$handler->handle($request)
gets called:public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// Chance to modify the request here before passing it into your application
// Pass the request on (to the next middleware or your application)
$response = $handler->handle($request);
// Chance to modify the response here before sending it back
return $response;
}
Last modified 4mo ago