LENKRAD - The modern PHP core
Basics
Advanced
Deployment

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.