I have built this helper that can be used as a general solution in your whole project:
if (! function_exists('url_add_query_params')) {
/**
* Add query parameters to an existing URL.
*/
function url_add_query_params(string $url, array $params): string
{
// Get an array of the query parameters from the target URL
parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $queryParams);
// Build the new target URL with the query parameters
return Str::of($url)
->before('?')
->append('?', Arr::query(
array_merge($queryParams, $params)
))
->rtrim('?')
->value();
}
}
Tested with PEST like this:
it('adds query params to an existing url', function (string $url, array $params, string $expected) {
expect(url_add_query_params($url, $params))->toBe($expected);
})->with([
'add-to-url-without-queryparams' => ['https://example.com', ['foo' => 'bar'], 'https://example.com?foo=bar'],
'add-to-url-with-queryparams' => ['https://example.com?foo=bar', ['baz' => 'qux'], 'https://example.com?foo=bar&baz=qux'],
'replace-existing-queryparam' => ['https://example.com?foo=bar', ['foo' => 'baz'], 'https://example.com?foo=baz'],
'remove-existing-queryparam' => ['https://example.com?foo=bar', ['foo' => null], 'https://example.com'],
'remove-single-existing-queryparam' => ['https://example.com?foo=bar&baz=qux', ['foo' => null], 'https://example.com?baz=qux'],
'remove-all-existing-queryparam' => ['https://example.com?foo=bar&baz=qux', ['foo' => null, 'baz' => null], 'https://example.com'],
'replace-queryparam-with-empty' => ['https://example.com?foo=bar', ['foo' => ''], 'https://example.com?foo='],
'replace-and-add-queryparams' => ['https://example.com?foo=bar', ['foo' => 'baz', 'baz' => 'qux'], 'https://example.com?foo=baz&baz=qux'],
'replace-param-and-remove-nonexisting' => ['https://example.com?foo=bar', ['foo' => 'baz', 'baz' => null], 'https://example.com?foo=baz'],
]);
Cheers, Pipo