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

Adam_Commit's avatar

Query Strings aand Parameters - Blowing my mind!

Hi community,

Running into a brick wall here with Query String/Parameter building, I have a feeling it shouldn't be this complicated but wanted to get best practice advice.

I am currently building a community platform that allows/requires users to tag their content. The content is tagged via two query string parameters.

Please note all relationships, tagging logic for posts including attaching/detaching is done, this is purely a filter system issue.

  1. Category - posts must have a category but only one category, on searching the query string would be appended as such. Eg. ?category=plants

  2. Tags - posts can have (optionally) many tags, this would append to the query string as such. Eg. ?tags=hardy

So far. I have created two functions (through a helper.php file) that "add_query_params" and "remove_query_params". These are helpful as it allows me to add and remove either ?category or ?tag without removing the other. MY PROBLEM is that I can not for the life of me seem to work out how to add MULTIPLE of the same tag to the query string to allow me to filter on MULTIPLE parameter options!

For example

I can build

website.com?category=plants&tags=hardy 

// I can also remove either tag without affecting the other

I cannot build

.com?category=plants&tags=hardy&tags=perenial
// (I can't add two of the same tag to the query string to allow me to filter on these in the controller/request

My functions that allow me to add/remove tags are as follows

/**
 * URL before:
 * https://example.com/orders/123?order=ABC009&status=shipped
 *
 * 1. remove_query_params(['status'])
 * 2. remove_query_params(['status', 'order'])
 *
 * URL after:
 * 1. https://example.com/orders/123?order=ABC009
 * 2. https://example.com/orders/123
 */
function remove_query_params(array $params = [])
{
    $url = url()->current(); // get the base URL - everything to the left of the "?"
    $query = request()->query(); // get the query parameters (what follows the "?")

    foreach($params as $param) {
        unset($query[$param]); // loop through the array of parameters we wish to remove and unset the parameter from the query array
    }

    return $query ? $url . '?' . http_build_query($query) : $url; // rebuild the URL with the remaining parameters, don't append the "?" if there aren't any query parameters left
}

/**
 * URL before:
 * https://example.com/orders/123?order=ABC009
 *
 * 1. add_query_params(['status' => 'shipped'])
 * 2. add_query_params(['status' => 'shipped', 'coupon' => 'CCC2019'])
 *
 * URL after:
 * 1. https://example.com/orders/123?order=ABC009&status=shipped
 * 2. https://example.com/orders/123?order=ABC009&status=shipped&coupon=CCC2019
 */
function add_query_params(array $params = [])
{

    $query = array_merge(
        request()->query(),
        $params
    ); // merge the existing query parameters with the ones we want to add


    return url()->current() . '?' . http_build_query($query); // rebuild the URL with the new parameters array
}


And in the blade comment they would be called like so

//Add query param
<a href="{{add_query_params(['tags' => $tag->id]) }}"
                class="inline-block bg-gray-100  px-3 py-1 text-xs uppercase font-button">
                #{{$tag->name}}
</a>


//Remove query param
<a href="{{remove_query_params(['category']) }}"
                class="inline-block bg-gray-300  px-3 py-1 text-xs uppercase font-button">
                #{{$has_category->name}}
                            
 </a>

It's driving me bonkers, most sites, e-commerce, travel sites allow you to update the query string and this approach I felt was the easiest to be called from anywhere in the site and agnostic from being tied down to a particular page, function, it also makes the builder extensible and reusable for more tags.

But I just can't work it out.

Anybody have any tips or direction on how to add multiple tags to the query string????

Cheers

0 likes
8 replies
automica's avatar

@adam_commit if you want multiple tags in your query string, you need to use an array

your-url?tags[]=hardy&tags[]=perennial
2 likes
rodrigo.pedra's avatar

Use the subscript operator ([]) to tell PHP to treat a group of query variables as an array:

website.com?category=plants&tags[]=hardy&tags[]=perenial

In Laravel you don't need to use the brackets to get the value back, just call the variable name:

$plants = request()->query('tags', []);

To manage query variables, I like to use this package:

https://uri.thephpleague.com/

But I think you should be fine with your custom implementation if it is working already.

1 like
Adam_Commit's avatar

Thank you very much @rodrigo.pedra, This makes perfect sense in terms of needing an array, I suppose my problem here is how would I go about constructing this using my functions, as currently, it does not append the query string with two parameters, but it strips the old one out at replaces it - eg url.com?tags=plants to url.com?tags=house

If I can work out how to push these values to the URL then I think I am onto a winner. Many thanks for your help!

Adam_Commit's avatar

Thank you very much @automica , This makes perfect sense in terms of needing an array, I suppose my problem here is how would I go about constructing this using my functions, as currently, it does not append the query string with two parameters, but it strips the old one out at replaces it - eg url.com?tags=plants to url.com?tags=house

If I can work out how to push these values to the URL then I think I am onto a winner. Many thanks for your help!

automica's avatar
automica
Best Answer
Level 54

@adam_commit you'll need to modify how you merge your params.

something like this:


function add_query_params(array $params = [])
{
	// replace this with the data you have within request()->query()
    $existingParams = [
        'tags' => [
            'bacon',
            'chicken'
        ],
        'colors' => [
            'green'
        ]
    ];

    foreach ($params as $key => $value) {

        // prevent duplication
        if (
            isset($existingParams[$key]) &&
            in_array($value, $existingParams[$key])
        ) {
            continue;
        }

        $existingParams[$key][] = $value;
    }

    return 'url?' . http_build_query($existingParams);
}

echo add_query_params(['tags' => 'duck', 'category' => 'meats']);
// returns 
url?tags%5B0%5D=bacon&tags%5B1%5D=chicken&tags%5B2%5D=duck&colors%5B0%5D=green&category%5B0%5D=meats

for removal

function remove_query_params(array $params = [])
{
    $existingParams = [
        'tags' => [
            'bacon',
            'chicken'
        ],
        'colors' => [
            'green'
        ]
    ];

    foreach ($params as $key => $value) {
        
        if (isset($existingParams[$value])) {
            unset($existingParams[$value]);
        }
    }

    return 'url?' . http_build_query($existingParams);
}

echo remove_query_params(['tags']);

//returns
url?colors%5B0%5D=green
1 like
Adam_Commit's avatar

@automica Thank you, this is kind of where I thought I needed to head, but this is a real point in the right direction from an implementation point of view. Thanks for the help.

automica's avatar

@adam_commit no problem.

I've just updated as I realized I was allowing duplication.

Hopefully this is enough to get you going again and provide you something to refactor as your own.

Please or to participate in this conversation.