Laravel Context

Laravel Tutorials

Deployment and Maintenance

Laravel Context lets you attach useful information to the work your application performs. You can add a request ID, user ID, tenant, route, or another diagnostic value once and Laravel will include that context in later log entries. The same information can also travel with queued jobs, which makes related activity easier to trace.

Use context for small pieces of metadata that explain where an operation came from. It does not replace application data, and it should not contain passwords, access tokens, or other secrets.

Add Context to a Request

Middleware is a practical place to establish context because it runs before your controller. The following middleware creates a trace ID and adds details that later log calls can reuse.

Example:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;

class AddRequestContext
{
    public function handle(Request $request, Closure $next)
    {
        // Use the supplied trace ID or create one for this request.
        $traceId = $request->header('X-Trace-ID', (string) Str::uuid());

        Context::add([
            'trace_id' => $traceId,
            'route' => $request->route()?->getName(),
            'user_id' => $request->user()?->id,
        ]);

        return $next($request);
    }
}

After this middleware runs, a normal log entry can carry the shared context without repeating every value.

Example:

use Illuminate\Support\Facades\Log;

// Laravel appends the active context to this log record.
Log::info('Order payment started', ['order_id' => $order->id]);

Add and Read Values

Pass a key and value to Context::add(), or pass an array when you have several values. Use addIf() when an existing value should win. This helps middleware and services cooperate without accidentally replacing earlier context.

Example:

use Illuminate\Support\Facades\Context;

// Add one value.
Context::add('tenant_id', $tenant->id);

// Add a default only when the key is missing.
Context::addIf('locale', 'en');

// Read and inspect context values.
$traceId = Context::get('trace_id');
$hasUser = Context::has('user_id');
$selected = Context::only(['trace_id', 'tenant_id']);
Method Purpose
get Returns a value or a supplied default.
has Checks whether a key exists.
only Returns selected context values.
except Returns all values except selected keys.
pull Returns a value and removes it.
forget Removes one or more values.

Propagate Context to Queued Jobs

Laravel automatically dehydrates the current context when you dispatch a queued job and hydrates it when a worker processes that job. You can therefore connect a web request to background work without adding tracing fields to every job constructor.

Example:

use App\Jobs\GenerateInvoice;
use Illuminate\Support\Facades\Context;

// Add metadata before dispatching the job.
Context::add(['order_id' => $order->id, 'trace_id' => $traceId]);
GenerateInvoice::dispatch($order->id);

The job can retrieve the restored value or simply write a log entry that includes it.

Example:

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

public function handle(): void
{
    // This value came from the request that dispatched the job.
    $traceId = Context::get('trace_id');

    Log::info('Generating invoice', [
        'trace_id_copy' => $traceId,
    ]);
}

Keep context compact. Large objects increase the payload that Laravel serializes with queued jobs.

Build Context Stacks

A stack stores several values under one key. It works well for breadcrumbs, completed processing stages, or other ordered diagnostic events.

Example:

use Illuminate\Support\Facades\Context;

// Record each stage in order.
Context::push('workflow', 'validated');
Context::push('workflow', 'payment_authorized');
Context::push('workflow', 'invoice_queued');

$steps = Context::get('workflow');

Use stacks for short labels rather than complete request bodies. That keeps logs readable and queue payloads manageable.

Use Hidden Context Carefully

Hidden context propagates with queued jobs but does not appear in log context. Add it with addHidden() when background work needs internal metadata that should not be written with every log entry.

Example:

use Illuminate\Support\Facades\Context;

// Pass an internal import identifier without adding it to logs.
Context::addHidden('import_batch_id', $batch->id);

$batchId = Context::getHidden('import_batch_id');

Hidden does not mean encrypted. Do not use hidden context as a safe place for credentials or sensitive personal information.

Limit Temporary Context with a Scope

Use Context::scope() when values should apply only while a callback runs. Laravel restores the previous context after the callback finishes, even when the callback throws an exception.

Example:

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

Context::scope(
    function () {
        // These values are active only inside this callback.
        Log::info('Importing customer records');
    },
    data: ['operation' => 'customer_import'],
    hidden: ['batch_id' => $batch->id],
);

Laravel Context Best Practices

  • Add stable identifiers such as a trace ID, request ID, user ID, or job ID.
  • Choose consistent key names so logs remain easy to search.
  • Add shared values once in middleware, listeners, or job-dispatching code.
  • Keep values small and serializable when queued jobs may receive them.
  • Remove temporary context after long-running operations, or use a scope.
  • Exclude passwords, tokens, payment details, and unnecessary personal data.

Conclusion

Laravel Context gives your logs and queued jobs a shared diagnostic trail. Add compact metadata early, retrieve it only when needed, use stacks for ordered events, and use scopes for temporary values. A consistent context strategy makes production issues easier to investigate without filling every method call with repeated tracing arguments.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram