31
JanTim Macdonald introduced a trait for Laravel middleware that allows you to pass arguments in a more PHP’ish way, including as a key =>
value pair for named parameters, and as a list for variadic parameters. Improves static analysis/IDE support, allows you to specify arguments by referencing the parameter name, enables skipping optional parameters (which fall back to their default value), and adds some validation so you don’t forget any required parameters by accident.
You can install this package through composer by running this command.
$ composer require timacdonald/has-parameters
To get started with an example, I’m going to use a stripped-back version of Laravel’s ThrottleRequests
. First up, add the HasParameters
trait to your middleware.
<?php
class ThrottleRequests
{
use HasParameters;
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $prefix = '')
{
//
}
}
You can now pass arguments to this middleware using the static with()
method, using the parameter name as the key
.
<?php
Route::stuff()
->middleware([
ThrottleRequests::with([
'maxAttempts' => 120,
]),
]);
You’ll notice at first this is a little more verbose, but I think you’ll enjoy the complete feature set after reading these docs and taking it for a spin.
Middleware::with()
The static with()
method allows you to easily see which values represent what when declaring your middleware, instead of just declaring a comma separate list of values. The order of the keys does not matter. The trait will pair up the keys to the parameter names in the handle()
method.
<?php
// before...
Route::stuff()
->middleware([
'throttle:10,1' // what does 10 or 1 stand for here?
]);
// after...
Route::stuff()
->middleware([
ThrottleRequests::with([
'decayMinutes' => 1,
'maxAttempts' => 10,
]),
]);
When your middleware
ends in a variadic parameter, you can pass an array of values for the variadic parameter key. Take a look at the following handle()
method.
<?php
public function handle(Request $request, Closure $next, string $ability, string ...$models)
Here is how we can pass a list of values to the variadic $models
parameter.
<?php
Route::stuff()
->middleware([
Authorize::with([
'ability' => PostVideoPolicy::UPDATE,
'models' => [Post::class, Video::class],
]),
]);
Some middleware will have different behavior based on the type of values passed through to a specific parameter. As an example, Laravel’s ThrottleRequests
middleware allows you to pass the name of a rate limiter to the $maxAttempts
parameter, instead of a numeric value, in order to utilize that named limiter on the endpoint.
<?php
// a named rate limiter...
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
});
// using the rate limiter WITHOUT an alias...
Route::stuff()
->middleware([
ThrottleRequests::with([
'maxAttempts' => 'api',
]),
]);
In this kind of scenario, it is nice to be able to alias the $maxAttempts
parameter name to something more readable.
<?php
Route::stuff()
->middleware([
ThrottleRequests::with([
'limiter' => 'api',
]),
]);
To achieve this, you can set up a parameter alias
map in your middleware.
<?php
class ThrottleRequests
{
use HasParameters;
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $prefix = '')
{
//
}
protected static function parameterAliasMap(): array
{
return [
'limiter' => 'maxAttempts',
// 'alias' => 'parameter',
];
}
}
Middleware::in()
The static in()
method very much reflects and works the same as the existing concatenation API. It accepts a list of values, i.e. a non-associative array. You should use this method if your handle()
method is a single variadic parameter, i.e. expecting a single list of values, as shown in the following middleware handle method
.
<?php
public function handle(Request $request, Closure $next, string ...$states)
{
//
}
You can pass through a list of states
to the middleware like so:
<?php
Route::stuff()
->middleware([
EnsurePostState::in([PostState::DRAFT, PostState::UNDER_REVIEW]),
]);
This package has a lot more features and validation methods with code examples, You can visit its complete documentation and source code on Github.
Published at : 31-01-2022
I am a highly results-driven professional with 12+ years of collective experience in the grounds of web application development especially in laravel, native android application development in java, and desktop application development in the dot net framework. Now managing a team of expert developers at Codebrisk.
Launch project