Voraussetzung: Du musst ein Laravel Projekt erstellt haben und dich im Projektordner befinden. Um ein Laravel Projekt zu erstellen folge unserem Tutorial oder nutze den Befehl composer create-project laravel/laravel mein-projekt.

Middleware erstellen: Drei Arten

Nachdem Du sichergestellt hast, dass ein Laravel Projekt vorhanden ist, öffnest Du nun das Terminal und navigierst zum besagten Projektordner. Gib dann den folgenden Befehl ein, der eine Middleware mit dem Namen “MyTrackingMiddleware” und eine gleichnamige PHP Datei im Ordern “app/Http/Middleware” erstellt.

Öffne dann die Datei “MyTrackingMiddleware.php” im Verzeichnis “app/Http/Middleware” und bearbeite sie, zum Beispiel mit Visual Studio Code.

Typ 1: Code vor der nächsten Middleware ausführen

<?php

namespace App\Http\Middleware;

use Closure;

class MyTrackingMiddleware
{
    public function handle($request, Closure $next)
    {
        // füge hier den Code ein, der vor dem nächsten Middleware-Handler ausgeführt werden soll.
        // Nützlich um beispielsweise den Request mit Daten anzureichern oder
        // ihn gar zu verwehren (zB. Auth oder Berechtigungsthemen)

        return $next($request);
    }
}

Dies ist der Anwendungsfall der am aller häufigsten verwendet wird.

An Stelle des Kommentars fügst du deine eigene Logik hinzu, die vor der nächsten Middleware ausgeführt werden soll. Der $request ist das eingehende Request-Objekt und $next ist der nächste Middleware-Handler.

Typ 2: Code nach der nächsten Middleware ausführen

Du kannst den nächsten Middleware Handler auch in einer Variable “parken” und bevor er final zurückgegeben wird noch einmal verändern.
Hierzu passe deine Middleware wie folgt an:

<?php

namespace App\Http\Middleware;

use Closure;

class MyTrackingMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // Hier kommt der Code rein, der nach der nächsten Middleware-Handler ausgeführt wird.
        // Sinnvoll um den Response vor dem Abschicken noch einmal zu verändern

        return $response;
    }
}

Typ 3: Code vor und nach der nächsten Middleware ausführen

Und natürlich lässt sich beides auch kombinieren.

<?php

namespace App\Http\Middleware;

use Closure;

class MyTrackingMiddleware
{
    public function handle($request, Closure $next)
    {
        // Code, der vor dem nächsten Middleware-Handler ausgeführt wird

        $response = $next($request);

        // Code, der nach dem nächsten Middleware-Handler ausgeführt wird

        return $response;
    }
}

Middleware registrieren

Jetzt haben wir sie zwar erstellt aber noch kommt sie nirgendwo zum Einsatz. Es gibt verschiedene Arten, wie Du nun die Middleware registrieren und nutzen kannst.
Der Aufbau der app/Http/Kernel.php Datei zeigt uns sogar, welche Typen es gibt:

  1. Global: protected $middleware
  2. Gruppiert nach web und api: protected $middlewareGroups
  3. Route spezifisch einsetzbar: protected $routeMiddleware

Nachfolgend die einzelnen Typen näher beschrieben.

1. Global registrieren

Wir bleiben in der app/Http/Kernel.php und schauen uns das erste Array einmal genauer an. Global in diesem Kontext bedeutet, dass diese Middleware immer ausgeführt wird.

/**
 * The application's global HTTP middleware stack.
 *
 * These middleware are run during every request to your application.
 *
 * @var array
 */
protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \Fruitcake\Cors\HandleCors::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

Hier befinden sich nun eine Reihe an registrierten Middlewares. Sie werden der Reihe nach abgearbeitet, beginnend von oben. Sie sind global und gelten für jeden HTTP-Request. Näheres dazu erfährst Du in unserem Laravel Middleware Onlinekurs bzw. im Laravel Powerkurs zum Thema Request-Lifecycle.

2. Registrieren pro Middleware Gruppe

Standardmäßig gibt es zwei Middleware Gruppen, nämlich web und api. Sie unterscheiden sich im Aufruf, zB. Accept: application/json führt zur API und “normale” Aufrufe werden zur Web Middleware geleitet. API ist Stateless (ohne Sessions) und Web hingegen hat Sessions (zB. für den User Login etc.).

/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \App\Http\Middleware\LocaleSwitcherMiddleware::class,
     //...
    ],
    'api' => [
        'throttle:200,1',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
 ];

Hier siehst Du schon, dass diese Middlewares zwar auch immer ausgeführt werden wenn man in der jeweiligen Gruppe ist.

3. Route spezifisch

Und hier wird’s dann völlig dynamisch. Denn du vergibst der Middleware einen Namen und das war’s zunächst einmal:

/**
 * The application's route middleware.
 *
 * These middleware may be assigned to groups or used individually.
 *
 * @var array
 */
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.optional' => \App\Http\Middleware\OptionalAuthenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'deine.middleware' => \App\Http\Middleware\MyTrackingMiddleware::class,
//...

In der letzten Array Zeile siehst Du sie, deine neue Middleware mit dem Namen deine.middleware. Und dann je nachdem wo Du es einsetzen möchtest, weist Du die Middleware der Route bzw. Controller Action zu:

Route::get('/', function () {
    // ...
})->middleware('deine.middleware');

Das kannst Du natürlich auch in einem Controller erledigen, indem Du im Konstruktur die Middleware hinzufügst. Das ist geschmacksache.

class DeinController extends Controller
{
    public function __construct() {
        $this->middleware(['deine.middleware'])->only(['index', 'show']);
    }
}

Ganz zu schweigen, kannst Du sie auch “nur” (engl. only) für bestimmte Actions zuweisen.

Fazit

Andreas Pabst hat 4,90 von 5 Sternen 106 Bewertungen auf ProvenExpert.com