Zum Hauptinhalt springen

Was ist Context?

Die Context-Funktion von Laravel ist ein Mechanismus, mit dem Sie Informationen über HTTP-Requests, Queue-Jobs und Commands hinweg speichern und teilen können. Wenn Sie über die Facade Illuminate\Support\Facades\Context Informationen hinzufügen, werden diese automatisch an alle Log-Einträge angehängt, die Ihre Anwendung schreibt. Dadurch lassen sich Informationen aus einzelnen Log-Aufrufen sauber von den geteilten Kontextdaten unterscheiden. Besonders nützlich ist das für Tracing in verteilten Systemen oder in Architekturen mit Queues.

Ausbreitung des Kontexts

Grundlegende Verwendung

Das typischste Muster ist das Setzen einer trace_id in einer Middleware. Alle nachfolgenden Log-Einträge enthalten sie dann automatisch.
1

Middleware erstellen

php artisan make:middleware AddContext
2

Trace-ID zum Kontext hinzufügen

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

class AddContext
{
    public function handle(Request $request, Closure $next): Response
    {
        Context::add('url', $request->url());
        Context::add('trace_id', Str::uuid()->toString());

        return $next($request);
    }
}
3

Middleware registrieren

Registrieren Sie sie in bootstrap/app.php als globale Middleware.
->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\App\Http\Middleware\AddContext::class);
})
Nach dieser Einrichtung werden Log-Einträge aus Controllern oder Services automatisch mit url und trace_id versehen.
Log::info('User authenticated.', ['auth_id' => Auth::id()]);
User authenticated. {"auth_id":27} {"url":"https://example.com/login","trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697"}

In den Kontext schreiben

add – Werte hinzufügen

use Illuminate\Support\Facades\Context;

Context::add('key', 'value');

// Mehrere Werte auf einmal hinzufügen
Context::add([
    'first_key'  => 'value',
    'second_key' => 'value',
]);
add überschreibt vorhandene Schlüssel. Möchten Sie nur hinzufügen, wenn der Schlüssel noch nicht existiert, verwenden Sie addIf.
Context::add('key', 'first');
Context::addIf('key', 'second');

Context::get('key');
// "first" – wird nicht überschrieben

increment / decrement – Zähler verwalten

Spezielle Methoden zum Erhöhen oder Verringern von Zahlenwerten. Der zweite Parameter gibt die Schrittweite an.
Context::increment('records_added');
Context::increment('records_added', 5);

Context::decrement('records_added');
Context::decrement('records_added', 5);

when – bedingt hinzufügen

Mit when können Sie je nach true-/false-Zweig unterschiedliche Werte hinzufügen.
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Context;

Context::when(
    Auth::user()->isAdmin(),
    fn ($context) => $context->add('permissions', Auth::user()->permissions),
    fn ($context) => $context->add('permissions', []),
);

push – auf einen Stack legen

Der Kontext unterstützt listenartige „Stacks”. Mit push fügen Sie Daten in der angegebenen Reihenfolge hinzu.
Context::push('breadcrumbs', 'first_value');
Context::push('breadcrumbs', 'second_value', 'third_value');

Context::get('breadcrumbs');
// ['first_value', 'second_value', 'third_value']
Beispiel für ein Query-Log als Stack:
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\DB;

// In der boot-Methode des AppServiceProvider registrieren
DB::listen(function ($event) {
    Context::push('queries', [$event->time, $event->sql]);
});

Kontext lesen

get / all

$value = Context::get('key');

// Alles abrufen
$data = Context::all();

only / except – nur Teile abrufen

$data = Context::only(['first_key', 'second_key']);

$data = Context::except(['first_key']);

pull / pop – abrufen und entfernen

pull liest den Wert eines Schlüssels und entfernt ihn zugleich aus dem Kontext.
$value = Context::pull('key');
Mit pop holen Sie den letzten Wert von einem Stack.
Context::push('breadcrumbs', 'first_value', 'second_value');

Context::pop('breadcrumbs');
// 'second_value'

Context::get('breadcrumbs');
// ['first_value']

remember – setzen, falls nicht vorhanden

$permissions = Context::remember(
    'user-permissions',
    fn () => $user->permissions,
);

has / missing – Existenz prüfen

if (Context::has('key')) {
    // ...
}

if (Context::missing('key')) {
    // ...
}
has liefert auch dann true, wenn null als Wert gespeichert ist. Geprüft wird lediglich, ob der Schlüssel existiert.

Kontext entfernen

Mit forget löschen Sie einen Schlüssel.
Context::add(['first_key' => 1, 'second_key' => 2]);

Context::forget('first_key');

Context::all();
// ['second_key' => 2]

// Mehrere auf einmal löschen
Context::forget(['first_key', 'second_key']);

Kontext mit Scope

Mit der Methode scope können Sie den Kontext nur während der Ausführung einer Closure vorübergehend ändern und den ursprünglichen Zustand danach automatisch wiederherstellen. Praktisch, wenn Sie in Tests oder lokalen Verarbeitungsschritten temporäre Zusatzinformationen ins Log aufnehmen möchten.
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;

Context::add('trace_id', 'abc-999');
Context::addHidden('user_id', 123);

Context::scope(
    function () {
        Context::add('action', 'adding_friend');

        $userId = Context::getHidden('user_id');

        Log::debug("Adding user [{$userId}] to friends list.");
        // Adding user [987] to friends list.  {"trace_id":"abc-999","user_name":"taylor_otwell","action":"adding_friend"}
    },
    data: ['user_name' => 'taylor_otwell'],
    hidden: ['user_id' => 987],
);

// Nach Verlassen des Scopes gelten wieder die ursprünglichen Werte
Context::all();
// ['trace_id' => 'abc-999']

Context::allHidden();
// ['user_id' => 123]
Ändern Sie innerhalb des Scopes ein Objekt, wirken sich diese Änderungen auch außerhalb des Scopes aus. Bei primitiven Werten ist das nicht der Fall.

Hidden Context

Daten, die nicht in Logs auftauchen sollen (Passwörter, API-Schlüssel, personenbezogene Daten), speichern Sie im Hidden Context. Sie können nicht mit der regulären get-Methode gelesen werden, sondern nur über dedizierte Methoden wie getHidden.
use Illuminate\Support\Facades\Context;

Context::addHidden('key', 'value');

Context::getHidden('key');
// 'value'

Context::get('key');
// null – nicht per regulärem get abrufbar
Für den Hidden Context stehen dieselben Methoden wie für den regulären Kontext zur Verfügung.
Context::addHidden(/* ... */);
Context::addHiddenIf(/* ... */);
Context::pushHidden(/* ... */);
Context::getHidden(/* ... */);
Context::pullHidden(/* ... */);
Context::popHidden(/* ... */);
Context::onlyHidden(/* ... */);
Context::exceptHidden(/* ... */);
Context::allHidden(/* ... */);
Context::hasHidden(/* ... */);
Context::missingHidden(/* ... */);
Context::forgetHidden(/* ... */);

Übergabe an Queue-Jobs

Beim Dispatchen eines Jobs wird der aktuelle Kontext automatisch serialisiert und in den Job-Payload eingebettet. Beim Ausführen des Jobs wird der ursprüngliche Kontext wiederhergestellt, sodass zum Beispiel die trace_id aus dem Request auch in Logs des Queue-Jobs erhalten bleibt.
// In der Middleware setzen
Context::add('trace_id', Str::uuid()->toString());

// Im Controller den Job dispatchen
ProcessPodcast::dispatch($podcast);
class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    public function handle(): void
    {
        Log::info('Processing podcast.', ['podcast_id' => $this->podcast->id]);
    }
}
Processing podcast. {"podcast_id":95} {"url":"https://example.com/login","trace_id":"e04e1a11-e75c-4db3-b5b5-cfef4ef56697"}
Sie sehen, dass die trace_id aus dem Request auch in Log-Einträgen aus dem Queue-Job erscheint.

Dehydrating – Anpassungen beim Verschicken des Jobs

Mit Context::dehydrating können Sie den Kontext unmittelbar vor dem Versand des Jobs anpassen. Zum Beispiel, um die durch den Header Accept-Language bestimmte Locale an die Queue zu übertragen.
// AppServiceProvider.php

use Illuminate\Log\Context\Repository;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Context;

public function boot(): void
{
    Context::dehydrating(function (Repository $context) {
        $context->addHidden('locale', Config::get('app.locale'));
    });
}
Verwenden Sie in der dehydrating-Callback nicht die Context-Facade, sondern ausschließlich das an die Callback übergebene $context-Repository. Andernfalls verändern Sie den Kontext des aktuellen Prozesses.

Hydrated – Wiederherstellung beim Ausführen des Jobs

Mit Context::hydrated können Sie unmittelbar nach dem Wiederherstellen des Kontexts vor der Job-Ausführung eingreifen. Zum Beispiel, um die zuvor gespeicherte Locale in die Konfiguration zu übernehmen.
// AppServiceProvider.php

use Illuminate\Log\Context\Repository;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Context;

public function boot(): void
{
    Context::hydrated(function (Repository $context) {
        if ($context->hasHidden('locale')) {
            Config::set('app.locale', $context->getHidden('locale'));
        }
    });
}
Auch in der hydrated-Callback dürfen Sie die Context-Facade nicht verwenden; nutzen Sie ausschließlich das übergebene $context-Repository.

Zusammenfassung

ContextLog::withContext
ReichweiteAlle Log-ChannelsNur ein bestimmter Channel
Übernahme in Queue-JobsAutomatisch (Dehydrate/Hydrate)Nein
Hidden DataUnterstütztNein
AnwendungsfallTracing / verteilte SystemeChannel-spezifische Metadaten
Da Hidden Context nicht in Logs erscheint, können Sie folgende Daten sicher speichern:
  • Session-IDs oder User-IDs (falls sie nicht in Logs auftauchen sollen)
  • API-Schlüssel oder Authentifizierungstoken
  • Locale oder Konfigurationswerte (sollen in die Queue übernommen, aber nicht geloggt werden)
  • Interne Flags oder Zustände
  1. Locale übernehmen: In dehydrating app.locale im Hidden Context speichern, in hydrated per Config::set wiederherstellen.
  2. Auth-Informationen weiterreichen: Informationen zum im Request authentifizierten Nutzer im Queue-Job weiter nutzbar machen.
  3. Tenant-ID: In Multi-Tenant-Anwendungen die Tenant-Kennung queue-übergreifend teilen.
Zuletzt geändert am 13. Juli 2026