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

julian2020's avatar

Add query parameter in middleware

For a demo mode (used in an iframe) I open my website with a query parameter, e.g.

?demo=true

I use this in order to do some other stylings conditionally. To keep this state while browsing to other links, I want to keep this get parameter in every single url. To do so, I created a middleware that checks whether the parameter is present or not and adds this parameter for the next request. Unfortunately the following does not work, the parameter bag is empty.

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

I know I could use the session for this as well but then I also would have enabled the demo mode by opening the website in another tab. In my mind adding the query parameter to every route would be the right approach. Pls can anyone help why the parameter bag is empty in the "next" request?

0 likes
5 replies
rodrigo.pedra's avatar

Hi @julianfaerber, when I need to add some parameter to a request a usually do this:

$request->merge([ 'foo' => 'bar']);

Be aware that unless you add it manually to all your links, the current request query parameters won't be added to all the links rendered in a blade view, or generated and returned in a JSON resource.

I would add this to the session and use a middleware to check for that value. The session should persist in several tabs on the same browser.

If you still want to keep as a query parameters, make sure you manually add them to the each generated URL, for example using the route(...) helper:

route('another.route', ['demo' => request('demo') ? 1 : 0])

I don't remember from which Laravel version, but named parameters not listed in the route path are added as a query parameter.

1 like
julian2020's avatar

Thank you @rodrigo.pedra for your reply!

Since I do not know a way to add the route parameter on each and every GET request in general (not by adding it to any route), I'll implement this by using a session.

It is true that other browser tabs will share the same session, which is not what I want, but there doesn't seem to be any other way.

Thank you!

1 like
rodrigo.pedra's avatar

One thing that crossed my mind is this:

You can create a custom helper to add the parameter to the routes or you can use your custom UrlGenerator.

Custom helper

For adding a custom helper, ideally you should add a custom helper file in your project's composer.json file for the sake o simplicity, and to test it out, you can define the custom helper on your './routes/web.php` file.

Add this function:

function custom_route($name, $parameters = [], $absolute = true)
{
    if (request()->query->get('demo') === '1') {
        $parameters = Arr::wrap($parameters);
        Arr::set($parameters, 'demo', 1);
    }

    return route($name, $parameters, $absolute);
}

Them replace every occurrence of the route() helper to this custom_route().

Custom UrlGenerator

This one is a bit tricker. Internally the route(...) helper uses the UrlGenerator's route(...) method, so you can create a class that extends from UrlGenerator and replace it on Laravel's Service Container.

1 - Create a class that extends the UrlGenerator, here I am placing in the ./app folder:

<?php

namespace App;

use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Arr;

class MyUrlGenerator extends UrlGenerator
{
    public function toRoute($route, $parameters, $absolute)
    {
        if ($this->request->query->get('demo') ===  '1') {
            $parameters = Arr::wrap($parameters);

            Arr::set($parameters, 'demo', 1);
        }

        return parent::toRoute($route, $parameters, $absolute);
    }
}

2 - To replace the UrlGenerator with this custom class in the Service Container, add the code below in your ./app/Providers/AppServiceProvider.php inside its register method:

$this->app->bind('url', function ($app) {
    return new MyUrlGenerator(
        $app['router']->getRoutes(), 
        $app['request'], 
        $app['config']['app.asset_url']
    );
});

Now every time you use the route(...) helper to generate a URL it will check for the query string.

===

IMPORTANT The big downside of both approach is to keep track of related changes in the framework code and update your custom helper or UrlGenerator to match those changes.

Other downside is the added overhead of checking the request's query parameters for every URL generated.

But, if this is a short lived demo that you can remove this custom code in a short time in the future, you can try this.

If it is code that would live forever I would not use it, as a mere update to the framework can break your project.

julian2020's avatar
julian2020
OP
Best Answer
Level 12

Thank you again für the code examples. I didn't try it by my own, but I think this should work. Maybe a little bit too much work, especially with the changes after each framework update.

On GitHub (https://stackoverflow.com/questions/6662542/check-if-site-is-inside-iframe) I found another way of "recognizing", if the app should use the demo mode or not. I added a helper method and simply added this code:

public static function isIframe() {
	return isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe';
}

I used this approach now because it totally fits my needs and is very easy. Additionally to this I store some settings in the session by using a Middleware:

if ($request->has('demo_setting_1')) {
	$request->session()->put('demo_setting_1', $request->input('demo_setting_1'));
}

return $next($request);

What do you think?

Please or to participate in this conversation.