On Thu, Dec 18, 2025 at 10:46 PM Máté Kocsis <[email protected]> wrote:
> Hi,
>
> The WHATWG URL living standard does the following:
>>
>> let url = new URL('https://example.com?debug&foo=bar&debug=');
>> console.log(
>> url.searchParams.toString(), //returns debug=&foo=bar&debug='
>> );
>>
>> the pair gets converted to ['debug' => '']. The roundtrip does not
>> conserve the query string as is but all key/pair (tuples) are present.
>>
>
> Yes, confirmed. Unfortunately, WHATWG URL only supports string values, so
> there's no way to support
> query parameters without a key (e.g. ?debug) in the RFC implementation
> either. :(
>
> On the other hand, the RFC 3986 implementation supports this notion, even
> uriparser calls this out
> in its documentation:
> https://uriparser.github.io/doc/api/latest/index.html#querystrings.
>
> However, there are a few other problems which came up when I was updating
> my implementation.
>
> 1.) Yesterday, I wrote that name mangling of the query params shouldn't
> happen. However, as I realized,
> it is still needed for non-list arrays, because the [..] suffix must be
> added to their name:
>
> $params = new Uri\Rfc3986\UriQueryParams()
> ->append("foo", [2 => "bar", 4 => "baz"]);
>
> echo $params->toRfc3986String(); //
> foo%5B2%5D=bar&foo%5B4%5D=baz
>
> var_dump($params->getFirst("foo")); // NULL
>
> Even though I appended params with the name "foo", no items can be
> returned when calling getFirst(),
> because of name mangling.
>
> 2.) I'm not really sure how empty arrays should be represented? PHP
> doesn't retain them, and they are
> simply skipped. But should we do the same thing? I can't really come up
> with any other sensible behavior.
>
> $params = new Uri\Rfc3986\UriQueryParams()
> ->append("foo", []);
>
> echo $params->toRfc3986String(); // ???
>
> 3.) We wrote earlier that objects shouldn't be supported when creating
> the query string from variables. But what about
> backed enums? Support for them in http_build_query() was added not long
> ago: https://github.com/php/php-src/pull/15650
> Should we support them, right?
>
> Regards,
> Máté
>
> Hi Máté
1.) Yesterday, I wrote that name mangling of the query params shouldn't
> happen. However, as I realized,
it is still needed for non-list arrays, because the [..] suffix must be
> added to their name:
When I talk about data mangling I am talking about this
parse_str('foo.bar=baz', $params);
var_dump($params); //returns ['foo_bar' => 'baz']
The bracket is a PHP specificity and I would not change it now otherwise
you introduce a huge BC break in the ecosystem
for no particular gain IMHO.
2.) I'm not really sure how empty arrays should be represented? PHP doesn't
> retain them, and they are
> simply skipped. But should we do the same thing? I can't really come up
> with any other sensible behavior.
> $params = new Uri\Rfc3986\UriQueryParams()
> ->append("foo", []);
This to me should yield the same result as ->append('foo', null); as the
array construct is only indicative of a repeating parameter name
if there is no repeat then it means no data is attached to the name.
3.) We wrote earlier that objects shouldn't be supported when creating
> the query string from variables. But what about
> backed enums? Support for them in http_build_query() was added not long
> ago: https://github.com/php/php-src/pull/15650
> Should we support them, right?
This gave me a WTF? moment (sorry for the language). Why was this change
added in PHP without a proper discussion in the internals
or even an RFC because it sets up a lot of precedence and even changes how
http_build_query is supposed to work in regards to objects.
If this had landed on the internal list I would have objected to it on the
ground as it breaks expectation in the function handling of type in PHP.
Do I agree with everything the function does ? No, but introducing
inconsistencies in the function is not a good thing. Now http_build_query
is aware of specific objects. Sringable or Travarsable objects are not
detected but Enum are ?? Pure Enum emits a TypeError but resource
do not ? Backed Enums are not converted to int or to string by PDO ? Why
would http_build_query do it differently ? The same reasoning apply as to
why Backed Enum does not have a Stringable interface.
Yes the output was "weird" in PHP8.1-> PHP8.3 but it was expected. Should
something be done for DateInterval too because the
output using http_build_query is atrocious ?
I still stand on my opinion that objects, resources should NEVER be
converted. In an ideal world only scalar + null and their repeated values
encapsulated in an array should be allowed; everything else should be left
to the developer to decide. So yes in your implementation I do think
that Backed Enum should not be treated differently than others objects and
should throw.
PS: I would even revert this change or deprecated it for removal in PHP9
(in a separate RFC)
Best regards,
Ignace