Adam Catlow
Adam Catlow

Reputation: 35

Laravel / PHP - Push multiple values to query string (same parameter)

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.

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

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

Upvotes: 3

Views: 6510

Answers (2)

crescast
crescast

Reputation: 91

You can try this:
.com?category=plants&tags=hardy,perenial.
Get tags in controller from query string as an array via
$tags = explode(',', request()->tags);

function for adding tags:

add_query_params(array $params = [])    {        
    // defining parameters being used in requests
    $tags = request()->tags;

    // param key (name) and its value being added
    $param = null
    $value = null;
    foreach($params as $key => $value){
        $param = $key;
        $value = $val;
    }

    // merging new ones
    switch ($key) {
        case 'tags':
            array_push($tags, $value)
            break;
        case 'some other param':
            // push value to array, like tags case
            break;
        default:
            break;
     }

     $query = array_merge(request()->query(),$tags);
     return http_build_query($query); 
     // rebuild the URL with the new parameters array 
} 

Upvotes: 1

pr1nc3
pr1nc3

Reputation: 8338

You can not do that. It's like you have a variable reassigned a new value. The old one will be lost.

What you can do is pass a comma-separated string like:

tags=test1,test2,test3

as values in your query param. Then use explode() function to make an array out of it and use the values.

Another idea is that your query parameter is created as an array so you should have something like:

tags[]=test1&tags[]=test2&tags[]=test3

That way when you request the parameter tags you already have an array in place to use and is closed to your first approach.

So you actually insert new values inside array tags

Upvotes: 1

Related Questions