Middleware
Middleware chaining is an important concept when working with LENKRAD. We are going to focus on routable classes here.
Concept
Middleware classes in routes need to implement \Neoan\Routing\Interfaces\Routable and be invokable (using an __invoke-method). Middleware can be chained and is commonly used for route-guards or retrieval of repetitive information (e.g. current user). The structure allows for route controllers to double as middleware and reuse their functionality.
Loading middleware
When using Attributes
?php
namespace App\Docs;
use App\Middleware\RequiresAuth;
use App\Middleware\RequiresWritePrivilege;
use Neoan\Provider\Injections;
use Neoan\Routing\Interfaces\Routable;
use Neoan\Routing\Attributes\Web;
// Attribute routing directly allows for middleware chaining.
// Here, both "RequiresAuth" and "RequiresWritePrivilege" is executed
// before resolving the route /docs/middleware
#[
Web(
'/docs/middleware',
'/docs/middleware.html',
RequiresAuth::class,
RequiresWritePrivilege::class
)
]
class Middleware implements Routable
{
public function __invoke(Injections $injections): array
{
// see "Declaring middleware"
return ['user' => $injections->get('user', null)];
}
}
When using Route declarations
?php
namespace App;
use Neoan\Routing\Route;
use App\Middleware\RequiresAuth;
use App\Middleware\RequiresWritePrivilege;
use App\Person\UpdatePerson;
// When chaining using the route class, the classes are invoked in order,
// effectively making the last class your controller
Route::put('/person/:id', RequiresAuth::class, RequiresWritePrivilege::class, UpdatePerson::class);
Declaring middleware
The structure of middleware does not differ from a controller, making it possible to use the cli to create middleware classes just as one would generate a controller.
Example
?php
namespace App\Middleware;
use Auth;
use Neoan\Routing\Interfaces\Routable;
use Neoan\Errors\Unauthorized;
use Neoan\Provider\Injections;
// This middleware stops execution and throws an unauthorized error if user is not logged in
class RequiresAuth implements Routable
{
// using "auth" (custom) and "injections" (included in core) from DI-container
public function __invoke(Auth $auth, Injections $injections): void
{
if(!$user = $auth->get()) {
new Unauthorized();
}
$injections->set('user', $user);
}
}
Passing on values
As seen in the example above, we are able to hook into the injection provider to write values to the following controllers in the chain. However, you might consider choosing to adjust your middleware to be used by the auto-wiring mechanism of the DI-container. To do so, make sure to return the running instance (see DI-container).
?php
namespace App\Middleware;
use Auth;
use Neoan\Routing\Interfaces\Routable;
use Neoan\Errors\Unauthorized;
class RequiresAuth implements Routable
{
// let's add a user array
public array $user;
// we can remove the injections and return ourselves
public function __invoke(Auth $auth): static
{
// let's use the local variable "user"
if(!$this->user = $auth->get()) {
new Unauthorized();
}
// finally, return the instance
return $this;
}
}
Before you move on
Many references on this page assume default settings. Your project might differ in behavior, paths etc.