On Fri, Dec 19, 2025 at 8:59 AM ignace nyamagana butera <[email protected]> wrote:
> 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 > > 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? Hi Máté, After further checking and researching, here's my view on Enum support. It is based on the PHP8.4 behaviour of Enum with json_encode since it is the base used to add its support in http_build_query. So in your implementation it would mean: allowed type: null, int, float, string, boolean, and Backed Enum (to minic json_encode and PHP8.4+ behaviour) arrays with values containing valid allowed type or array. are also supported to allow complex type support. Any other type (object, resource, Pure Enum) are disallowed they should throw a TypeError Maybe in the future scope of this RFC or in this RFC depending on how you scope the RFC you may introduce an Interface which will allow serializing objects using a representation that follows the described rules above. Similar to what the JsonSerializable interface is for json_encode. If such interface lands, then Pure Enum serialization will be allowed. via the interface and the behaviour of BackedEnum also would be affected just like what is happening with json_encode. (ie: the interface takes precedence over the class instance default behaviour). Last but not Last, all this SHOULD not affect how http_buid_query works. The function should never have been modified IMHO so it should be left untouched by all this except if we allow it to opt-in the behaviour once the interface is approved and added to PHP. What do you think ? Best regards, Ignace
