Symfony's Request object has a query property that is of type
ParameterBag, this maintains an iterable list of parameters. The ParameterBag however is not directly translatable to a query string. This causes issues when trying to use the getQueryString() method after modifying the ParameterBag parameters.
Solution 1 - Create a new query string:
$request = \Drupal::request();
$parameter_bag = $request->query;
$parameter_bag->remove('destination');
// This has to be http_build_query() because
// \Drupal::request()->getQueryString() returns the original query string
// but here we need the modified query string (without destination).
$query = http_build_query($parameter_bag->all());
Solution 2 - Update all global variables:
\Drupal::request()->query->remove('destination');
\Drupal::request()->overrideGlobals();
$query = \Drupal::request()->getQueryString();
Reference to overrideGlobals()
The main issue is that getQueryString()
returns the global server variable query string which doesn't reflect changes to the parameter bag. So editing the parameters is not as straight forward as it used to be. We either have to build a new query string or override ALL global variables. In my particular use case I thought that overwritting all globals was too wide reaching and it would overwrite any changes that other modules implemented that our specific code has no control over so I went with solution 1 above as it is generally a safer piece of code to implement.
My two options for solving this the right way is that:
1) ParameterBag either needs a method to build a query string
2) The request object needs to be able to return modified query parameters. Probably by deprecating / defaulting the existing function to returning the output of a new function called getQueryStringOriginal() and creating another new function called getQueryStringModified().