Mastering Global State with Laravel Context
Overview
Managing state across a
Prerequisites
To follow this guide, you should be comfortable with:
- PHP 8.2+ and Laravelsyntax.
- Laravel Middlewareimplementation.
- The basics of Laravel Queuesand Job dispatching.
Key Libraries & Tools
- Laravel Context: The core service for managing shared request data.
- Ray: A specialized debugging tool for inspecting variables and logs in real-time.
- PHPStorm: The IDE used for navigating the codebase and managing PHP environments.
Code Walkthrough
Setting Data in Middleware
First, capture the user's preferred locale from the request headers and store it in the context.
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Context;
use Closure;
class AddContext
{
public function handle($request, Closure $next)
{
$locale = $request->getPreferredLanguage(['en', 'de']);
Context::addHidden('locale', $locale);
app()->setLocale($locale);
return $next($request);
}
}
Using addHidden ensures this sensitive data doesn't clutter your standard log files while remaining accessible to the application.
Automatic Hydration in Service Providers
When a Job runs on a separate process, the application state resets. To persist the locale, use the hydrated hook in your AppServiceProvider.
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Config;
public function boot(): void
{
Context::hydrated(function ($context) {
if ($context->hasHidden('locale')) {
app()->setLocale($context->getHidden('locale'));
}
});
}
This hook triggers automatically when a queued job starts, pulling the stored "hidden" locale from the context and applying it to the new process's configuration.
Syntax Notes
Laravel provides two primary methods for adding data: Context::add() and Context::addHidden(). The hidden variant is specifically designed for metadata you want to propagate to jobs but exclude from automatic logging. This distinction is a best practice for maintaining clean, readable logs.
Practical Examples
- Multi-tenant Applications: Store the
tenant_idat the start of a request to ensure all downstream database queries and queued reports target the correct client. - Distributed Tracing: Generate a
trace_idin a global middleware to link web requests to async jobs in your logging dashboard.
Tips & Gotchas
Avoid manually setting config values inside your Job's handle() method. While it works for that specific class, it won't affect secondary jobs or notifications dispatched from within that job. Always use the Context::hydrated hook to ensure the environment is correctly configured for the entire execution tree.
