Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129666 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id B564C1A00BC for ; Sat, 20 Dec 2025 12:01:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1766232073; bh=1V4no3CUkvvrioUKIBvWlVzgFWJAQYD/GaGuR4+SlPU=; h=References:In-Reply-To:From:Date:Subject:To:From; b=GzjIKK4Y0qbZv0EEV10pVnBGl1vp/H/3B+eIYTHnyW8fchQYKqAitQxoQ0omJjLJn gjubZn5AWbc7kgBg9qxPkNsT2a45u+WYrmnGcf8hoxzwBQfArF5F90Ep62JrCOukig 52JRXaz2EiBceBxAnB4iH+Vq1ihCcwLtMSJ2VdPOWtxtNB6pGWNb6WuNkYtbHvVIq9 8AHk8uV27aeOUNr9i/SBJUZQxE/PttWxdM9w2Lx14GyEMEkWCAUzQf9Frn/wWBm/yK ELzMhsWLoEEb4YfUnQrKEyTHgU3cea5lch7T+CgLjNTrciFEQzNvQookEo1bFzzMps XJCHVmfQGzt+A== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0019C1801D9 for ; Sat, 20 Dec 2025 12:01:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,T_SPF_TEMPERROR autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-oa1-f50.google.com (mail-oa1-f50.google.com [209.85.160.50]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sat, 20 Dec 2025 12:01:08 +0000 (UTC) Received: by mail-oa1-f50.google.com with SMTP id 586e51a60fabf-3f5ec7636e2so980460fac.2 for ; Sat, 20 Dec 2025 04:01:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766232063; x=1766836863; darn=lists.php.net; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=OZ2j8x+pGENzAvmWm8fR6bEW2EFQdwegHh1Sh8R2dws=; b=PxLNcmiMnr7b4cRMJVR25KQdfpH7a72rM9KMIr01Al9zSPhM5Yhy+mLAWVBHjbOn9a F0ryVewISF99N7FVS9rOKOBCsGuFRsmKvqAOJyMDrW4u8ww16chP3SqDdjMpVzObjx4w 02IGAYaUOAMap9XmieiaWy/enOlcUXfavkeeHpUCVB1ubNjCyzgnktTf8DYNUOkAXpmG 0b7lUbjh9ajEZJARbf1El/PpzWygVmo8qnvbU1vbG1gd7RALC5+KxwTn8qIkmhugKyd5 bPO94ZCYT+5DigSwFpWe7uvLIJUVkRk24GPT+8o9GtfCbu0qWD6E0azzqox66qDdI9q8 taDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766232063; x=1766836863; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=OZ2j8x+pGENzAvmWm8fR6bEW2EFQdwegHh1Sh8R2dws=; b=Ic7FDAzNjh1GX0hFXyBDg1nJIcXyLV6abtew4yhtm60nSpXNGrAGaTTNEJxxVSFyCW LL+PRbCyGohC7VKBIkOApnmOznmc2Xb00eMs+Fz+taTfgowXYHBEsuykUx3JseSVxcF+ pIxIqvdfCv9nGy792RWS1ME+RKhgTldGmA/KMkNLPgqDnz8yio096ZyPUbwWK+DzOflD pc+XV4tO0kfcriYABKSjaLJnILF9RDYFubqXzVVxcXIBNwy2wd3NnwFZI65mCiDioJwY 4K40kS2JxIknEd8mZBg5/2TC8nPq5bW9Xox6WLTkPL4kh/gXOgzB9YOo8+eEk2fFqVYK RW8g== X-Forwarded-Encrypted: i=1; AJvYcCXbjVjjy38gXb6RwbwTjRo6yyNkh8zzeUF/+wOE9vVbjXHtdYA99Tl7o5XKJhO/sI1t5+0wUq5T/iE=@lists.php.net X-Gm-Message-State: AOJu0Yxljrn3TQxweXs1n94RfmgCrjESiD1skeor3IiHfGtK7lta7Z31 sfT6BjuozhOIjvnl4pBJmsGPLAXI0AAusIidGMYCZ+GDCEao2M1Vpu1X4NN2RgZVEETBYcnCGQj HSqW9LTnubXLWlCx3WLVn62sqbWZZ1tA= X-Gm-Gg: AY/fxX49Y1DcsL6xMT1PaBi4ckBn/MVOitREydsF9XDRXEHWDalRjHqGRr7YDjYycuX VtJ3p1w3p97jowZX9DU2TGikY9DAp3yOeGBgQCKADOJFHFwTApEWGyJj1hVuP4o6v6xc4Fzv28D qqElcoeIELyPhDI/I2TABhb5k1VbKdHnjzWslCVbm3ihFHqHFQkqXyuZT+EmVD4pSqIrVe3WUIJ JAnx1fdXV3//NrOPVPdkDeVpzGSVStzYRFCqVzLA5g5W/KZMIBpt/37hMwGj5Vg3A9okIlX3mKR BCOJ4PbYbJxpqShqr/RzpxiAQujS0piXxvXDv8l2 X-Google-Smtp-Source: AGHT+IFllY1I5CABe5pR4TZSFPhgPKg81tozpTHQ2RQPA8cLaLpKh1q/ktbpVmQK+4ZfHIPHQx8qf6BG8V9NmH261ic= X-Received: by 2002:a05:6820:1507:b0:65c:fb36:f239 with SMTP id 006d021491bc7-65d0e9212c1mr2159179eaf.9.1766232062985; Sat, 20 Dec 2025 04:01:02 -0800 (PST) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <83238ad3-c844-4457-dfb3-11321787e022@php.net> In-Reply-To: Date: Sat, 20 Dec 2025 13:00:51 +0100 X-Gm-Features: AQt7F2rzeLRffb79u_a0_E6eEDp6sGrNrbqbnai76OB5otblh9BT5YEJR1QrGsw Message-ID: Subject: Re: [PHP-DEV] [RFC] [Discussion] Followup Improvements for ext/uri To: =?UTF-8?B?TcOhdMOpIEtvY3Npcw==?= , PHP Internals List Content-Type: multipart/alternative; boundary="000000000000b49557064660f234" From: nyamsprod@gmail.com (ignace nyamagana butera) --000000000000b49557064660f234 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Fri, Dec 19, 2025 at 8:59=E2=80=AFAM ignace nyamagana butera wrote: > On Thu, Dec 18, 2025 at 10:46=E2=80=AFPM M=C3=A1t=C3=A9 Kocsis > wrote: > >> Hi, >> >> The WHATWG URL living standard does the following: >>> >>> let url =3D new URL('https://example.com?debug&foo=3Dbar&debug=3D'); >>> console.log( >>> url.searchParams.toString(), //returns debug=3D&foo=3Dbar&debug=3D' >>> ); >>> >>> the pair gets converted to ['debug' =3D> '']. 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, s= o >> 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, eve= n >> 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 updatin= g >> 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 =3D new Uri\Rfc3986\UriQueryParams() >> ->append("foo", [2 =3D> "bar", 4 =3D> "baz"]); >> >> echo $params->toRfc3986String(); // >> foo%5B2%5D=3Dbar&foo%5B4%5D=3Dbaz >> >> 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 =3D 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=C3=A1t=C3=A9 >> >> Hi M=C3=A1t=C3=A9 > > 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=3Dbaz', $params); > var_dump($params); //returns ['foo_bar' =3D> '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 =3D 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 ho= w > 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 th= e > 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 lef= t > to the developer to decide. So yes in your implementation I do think > that Backed Enum should not be treated differently than others objects an= d > 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=C3=A1t=C3=A9, 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 --000000000000b49557064660f234 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Fri, Dec 19, 2025 at 8:59=E2=80=AFAM i= gnace nyamagana butera <nyamsprod= @gmail.com> wrote:
On Thu, Dec 18, 2025 at 10:46=E2=80=AFPM M=C3=A1t=C3=A9 Kocsi= s <kocsismat= e90@gmail.com> wrote:
Hi,
The WHATWG URL l= iving standard does the following:
let url =3D new URL(=
'https://example.com?debug&foo=3Dbar&debug=3D'<=
/span>);
console.log(
url.searchParams.= toString(), //returns debug=3D&a= mp;foo=3Dbar&debug=3D'
);
the pair gets con= verted to ['debug' =3D> '']. The roundtrip does not cons= erve the query string as is but all key/pair (tuples) are present.

Yes, confirmed. Unfortunat= ely, WHATWG URL only supports string values, so there's no way to suppo= rt
query parameters without a key (e.g. ?debug) in the RFC implem= entation either. :(

On the other hand, the RFC 398= 6 implementation supports this notion,=C2=A0even uriparser calls this out
=C2=A0
However, there are a few other problems which came up when I was updating= my implementation.

1.) Yesterday, I wrote that na= me mangling of the query params shouldn't happen. However, as I realize= d,
it is still needed for non-list arrays, because the [..] suffi= x must be added to their name:

$params =3D new Uri= \Rfc3986\UriQueryParams()
=C2=A0 =C2=A0 ->append("foo", [2 = =3D> "bar", 4 =3D> "baz"]);

echo $params-&= gt;toRfc3986String();=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 // foo%5B2%5D=3Dbar&foo%5B4%5D=3Dbaz

var_dump($params->getFirst("foo"));=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// NULL

Even though I appended params with the name "foo"= ;, no items can be returned when calling getFirst(),
because of n= ame mangling.

2.) I'm not really sure how empt= y arrays should=C2=A0be 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 =3D new Uri\Rfc3986\UriQueryParams()
=C2=A0 =C2=A0 ->append(&q= uot;foo", []);

echo $params->toRfc3986String();=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // ???

3.) We wrote earlier that objects shouldn't be sup= ported when creating the=C2=A0query 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 s= upport them, right?

Regards,
M=C3=A1t=C3= =A9

Hi M=C3=A1t=C3=A9=C2= =A0

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:=C2=A0

= When I talk about data mangling I am talking about this

p= arse_str('foo.bar=3Dbaz', $params);
var_dump($params); //returns= ['foo_bar' =3D> 'baz']

The bra= cket is a PHP specificity=C2=A0and 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=C2=A0be represen= ted? PHP doesn't retain them, and they are
simply skipped. But shoul= d we do the same thing? I can't really come up with any other sensible = behavior.
$params =3D new Uri\Rfc3986\UriQueryParams()
=C2=A0 =C2=A0 = ->append("foo", []);

This to m= e should yield the same result as ->append('foo', null);=C2=A0 a= s 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.= =C2=A0

3.) We wrote earlier that objects shouldn't be supported w= hen creating the=C2=A0query string from variables. But what about
backed= enums? Support for them in http_build_query() was added not long ago:=C2= =A0= https://github.com/php/php-src/pull/15650
Should we support them, ri= ght?

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 prec= edence 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 hand= ling 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=C2= =A0or Travarsable objects are not detected but Enum are ?? Pure Enum emits = a TypeError but resource
do not ? Backed Enums are not conv= erted to int or to string by PDO ? Why would http_build_query do it differe= ntly=C2=A0? The same reasoning apply as to
why Backed Enum does n= ot have a Stringable interface.

Yes the output was= "weird" in PHP8.1-> PHP8.3 but it was expected. Should someth= ing be done for DateInterval too because the
output using http_bu= ild_query is atrocious ?

I still stand on my opini= on that objects, resources should NEVER be converted. In an ideal world onl= y scalar=C2=A0+ null and their repeated values
encapsulated in an= array should be allowed; everything else should be left to the developer t= o decide. So yes in your implementation I do think
that Backed En= um should not be treated differently than others objects and should throw.<= /div>

PS: I would even revert this change or deprecated = it for removal in PHP9 (in a separate RFC)

Best re= gards,
Ignace

<= br>

3= .) We wrote earlier that objects shouldn't be supported when creating t= he=C2=A0query string from variables. But what about
backed enums? Suppor= t for them in http_build_query() was added not long ago:=C2=A0https://github.c= om/php/php-src/pull/15650
Should we support them, right?=C2=A0

Hi M=C3=A1t=C3=A9,

Afte= r 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 b= ase used to add its support in http_build_query.

S= o in your implementation it would mean:

allowed ty= pe: null, int, float, string, boolean, and Backed Enum (to minic json_encod= e and PHP8.4+ behaviour)
arrays with values containing valid allo= wed type or array. are also supported to allow complex type support.
<= div>
Any other type (object, resource, Pure Enum)=C2=A0=C2=A0= 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=C2=A0an Interface which will allow serializing ob= jects using a representation that
follows the described rules abo= ve. Similar to what the JsonSerializable=C2=A0interface is for json_encode.=

If such interface lands,=C2=A0then Pure Enum = serialization will be allowed. via the interface and the behaviour of Backe= dEnum also would be affected just like what is happening=C2=A0with json_enc= ode. (ie: the interface=C2=A0takes precedence over the class instance defau= lt behaviour).

Last but not Last, all this SHOULD = not affect how http_buid_query works. The function should never have been m= odified 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 add= ed to PHP.

What do you think ?
Best rega= rds,
Ignace
--000000000000b49557064660f234--