0

Request macros and custom request mixins

Advanced5 min read·lv-09-007
laravel-src

Concept

Request lifecycle and the container — understanding how the Request object flows through Laravel's systems, what modifies it, and how it's accessible globally.

How Request is created: public/index.phpApplication::handle(Request::capture()). Request::capture() reads from PHP superglobals ($_GET, $_POST, $_FILES, $_COOKIE, $_SERVER) at the framework boot. This single Request object is shared throughout the entire request lifecycle.

Container binding: The Request is bound into the container as 'request' and as Illuminate\Http\Request::class. When you inject Request $request in a controller, you get the same object that middleware has been modifying all along. Attribute modifications from middleware ($request->attributes->set(...), $request->merge(...)) persist for the controller.

Route parameters on the Request: After route matching, route parameters are added to the Request via $request->setRouteResolver(). Access them: $request->route('user_id') — get a specific route parameter. $request->route() returns the current Route object.

request() helper: request() with no args returns the current Request. request('key') is equivalent to $request->input('key'). request()->user() returns the authenticated user (alias for auth()->user()).

Request in queue jobs and commands: Jobs and commands run outside the HTTP request cycle. There is no Request — calling request() in a job returns an empty request object. Pass all needed data to the job constructor explicitly.

Code Example

php
<?php
// request() helper — equivalent to injecting Request
$input = request('name');              // get input
$user  = request()->user();            // get authenticated user
$ip    = request()->ip();              // get client IP
$full  = request()->fullUrl();         // get full URL

// Route parameters on request
// Route: /orders/{order}/items/{item}
public function showItem(Request $request, Order $order): void
{
    // After route model binding, route params are on the request
    $orderId = $request->route('order'); // the bound Order model (not the ID string)
    $itemId  = $request->route('item');
    $route   = $request->route();       // the Route object itself
    $name    = $request->route()->getName(); // "orders.items.show"
}

// Attributes set by middleware — available in controller
// In AuthMiddleware:
// $request->attributes->set('user_permissions', $user->permissions);
// In controller:
$permissions = $request->attributes->get('user_permissions');

// WRONG — calling request() inside a job
class ProcessOrderJob implements ShouldQueue
{
    public function handle(): void
    {
        $userId = request()->user()->id; // BUG: no HTTP request in job context!
    }
}

// CORRECT — pass data in job constructor
class ProcessOrderJob implements ShouldQueue
{
    public function __construct(
        private readonly int $userId,
        private readonly int $orderId,
    ) {}

    public function handle(): void
    {
        $user  = User::find($this->userId);
        $order = Order::find($this->orderId);
    }
}

// Checking if running in HTTP context
if (app()->runningInConsole()) {
    // CLI/queue — no request available
} else {
    // HTTP context — request is available
    $ip = request()->ip();
}