Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mate89's avatar

Pass variables from middleware to controller

I created a middleware which can recognize the customer based on my own logic.

So I'm passing the $request->customer variable through the chain to the controller. This works fine with the "Illuminate\Http\Request" request in my controller. But if I want to create a POST route which has a specific Request, like "OrderCreateRequest", the customer property does not arrive.

Middleware:

public function handle(Request $request, Closure $next): Response {
    $request->customer = /** geting customer */;

    $response = $next($request);

    return $response;
}

Validation Request:

class OrderCreateRequest extends FormRequest {
    public Customer $customer;

    public function rules(): array {
        return [/** validation rules */];
    }
}

Controller:

class CheckoutController extends Controller {
    public function createOrder(OrderCreateRequest $request): RedirectResponse {
        dd($request->customer); // null
    }
}

Actually I tried to create a new "OrderCreateRequest" request in the middleware in case of this route, but I guess the laravel creates a new one before inject it to the controller. (I check spl_object_hash in the middleware and in the controller and the two hashes was not match.) I think the laravel does not clone the incoming request, create a new one and copy the properties, therefore my customer property has gone.

How should I do this? Thanks for the answers in advance!

0 likes
15 replies
Pippo's avatar

Try to use in the middleware:

$request->merge(['customer' => $customer /** the getted customer **/]);

instead of

$request->customer = /** geting customer */;
2 likes
mate89's avatar

@Pippo Thanks! I found the merge method in that moment before you wrote. It really works fine, just it not a nice solution I guess because the customer is not an input parameter and the merge put it to the inputBag. But if nobody has any other idea I will use it.

mate89's avatar

I think I found the solution. It can a more elegant way to pass parameter through the pipeline, if use attributes for this purpose. In the mIddleware:

$request->attributes->add(['customer' => $customer]);

And the controller:

$request->attributes->get('customer');

Not so comfortable but more elegant.

1 like
Pippo's avatar

A better solution could be "binding-instances"

In middleware:

app()->instance('customer',  $customer);

Then in controller:

$customer = resolve('customer');

(I've never tried it)

1 like
mate89's avatar

@Pippo It's a nice feature, I've never heard it before, thanks! But I guess it creates a singleton object which is not recommended to use in case of request dependent objects. I think I will stay the merge or the attribute solution.

jaseofspades88's avatar

Why? What are you trying to achieve by passing data from a middleware to a controller?

mate89's avatar

@jaseofspades88 because I'd like to use the customer object in every controller and I don't want to handle it each times. Like in other frameworks for example laminas/mezzio, you can pass attributes through the pipeline.

Snapey's avatar

better to call a service CustomerResolver from the controller and get the result there.

1 like
mate89's avatar

@Snapey Thanks! It sounds interesting! In that case the service can depend on the request?

jaseofspades88's avatar

@mate89 No. Have a service that is responsible for getting the customer. This can be used anywhere. You'd be able to inject this service into any controller and you'd be able to resolve it out of the container from anywhere. Make it agnostic so it doesn't care if it's in a middleware, form request, controller or even a static class.

mate89's avatar

@jaseofspades88 Sorry, my fault! I forget to tell you in my first post, that the logic which i use to identify the custmer is cookie based, that's why i think / thought it should to depend on request. In that case is the service is the best solution?

Snapey's avatar

@mate89 the request will be available in all places except things that don't have a request like queue and scheduled jobs, and cli commands

Please or to participate in this conversation.