# Stop replacing dots with underscores in query, post and cookie parameters for PHP 8?

- Thread: https://externals.io/message/106213
- Original archive: https://news-web.php.net/php.internals/106213
- Started by Arnold Daniels on 2019-07-16T01:39:49+00:00
- Messages: 15
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #106213 — Arnold Daniels — 2019-07-16T01:39:49+00:00

URL: https://externals.io/message/106213#106213

Hi,

PHP replaces dots with underscores for $_GET, $_POST and $_COOKIE. This behavior once made sense because of Register globals. The explanation in the manual also still implies that query and post parameters are converted to variables (see https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names). Register globals has been removed since 5.4.0 and thus this behavior serves little purpose.

I think it would be good to remove the conversion in PHP 8, as it's a general cause of confusion and annoyance for anyone who comes across it.

Is there a good reason to keep this behavior in PHP 8?

Yours,
Arnold

[Arnold Daniels - Chat @ Spike](https://www.spikenow.com/?ref=spike-organic-signature&_ts=2oznd)	[2oznd]

---

## #106214 — Sara Golemon — 2019-07-16T02:38:58+00:00

URL: https://externals.io/message/106213#106214

On Mon, Jul 15, 2019 at 8:39 PM Arnold Daniels <arnold.adaniels.nl@gmail.com>
wrote:
> PHP replaces dots with underscores for $_GET, $_POST and $_COOKIE.
> This behavior once made sense because of Register globals.
> The explanation in the manual also still implies that query and
> post parameters are converted to variables
> (see
https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
).
> Register globals has been removed since 5.4.0 and thus this behavior
serves little purpose.
>
> I think it would be good to remove the conversion in PHP 8, as it's a
general cause of confusion and annoyance for anyone who comes across it.
>
> Is there a good reason to keep this behavior in PHP 8?
>
IMO, we can safely kill this.  If anyone needs this behavior preserved, it
can be mimicked with half a dozen lines of PHP, or heck we can include a
function to call.  I will, however, be very surprised if anyone misses this
by now.

-Sara

---

## #106215 — Guilliam Xavier — 2019-07-16T06:45:02+00:00

URL: https://externals.io/message/106213#106215

>
> On Mon, Jul 15, 2019 at 8:39 PM Arnold Daniels <arnold.adaniels.nl@gmail.com>
> wrote:
> > […]
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> ).
> > […]
> serves little purpose.
> > […]
> general cause of confusion and annoyance for anyone who comes across it.
> > […]
> IMO, we can safely kill this.  If anyone needs this behavior preserved, it
> can be mimicked with half a dozen lines of PHP, or heck we can include a
> function to call.  I will, however, be very surprised if anyone misses this
> by now.
>
> -Sara

Indeed, it seems that people are rather strugling to work around the
current behavior (and have been for years)... Some examples:

- https://bugs.php.net/bug.php?id=40000
- https://stackoverflow.com/questions/68651/get-php-to-stop-replacing-characters-in-get-or-post-arrays
- https://github.com/symfony/symfony/issues/9009
- https://github.com/api-platform/core/issues/509
- https://github.com/api-platform/core/blob/v2.4.5/src/Util/RequestParser.php

-- 
Guilliam Xavier

---

## #106216 — Nikita Popov — 2019-07-16T07:50:40+00:00

URL: https://externals.io/message/106213#106216

On Tue, Jul 16, 2019 at 3:40 AM Arnold Daniels <arnold.adaniels.nl@gmail.com>
wrote:

> Hi,
>
> PHP replaces dots with underscores for $_GET, $_POST and $_COOKIE. This
> behavior once made sense because of Register globals. The explanation in
> the manual also still implies that query and post parameters are converted
> to variables (see
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names).
> Register globals has been removed since 5.4.0 and thus this behavior serves
> little purpose.
>
> I think it would be good to remove the conversion in PHP 8, as it's a
> general cause of confusion and annoyance for anyone who comes across it.
>
> Is there a good reason to keep this behavior in PHP 8?
>

This has been discussed a few times already, and I think that everyone
agrees that this behavior should go, but not necessarily on the migration
path. There is an RFC here: https://wiki.php.net/rfc/on_demand_name_mangling
I think that the latest version of that RFC, that basically proposes to
drop the behavior and tell people to use a polyfill is fine.

Nikita

---

## #106217 — Bishop Bettini — 2019-07-16T12:33:40+00:00

URL: https://externals.io/message/106213#106217

> On Tue, Jul 16, 2019 at 3:40 AM Arnold Daniels <
> arnold.adaniels.nl@gmail.com>
> wrote:
>
> > […]
> converted
> > […]
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> ).
> > […]
> serves
> > […]
>
> This has been discussed a few times already, and I think that everyone
> agrees that this behavior should go, but not necessarily on the migration
> path. There is an RFC here:
> https://wiki.php.net/rfc/on_demand_name_mangling
> I think that the latest version of that RFC, that basically proposes to
> drop the behavior and tell people to use a polyfill is fine.
>

I've readied the proposal for formal discussion. As proposed:

   - PHP 8.0 will no longer mangle variable names in any super-global.
   - The changelog will recommend auditing super-global access for mangled
   names, and replacing with the actual variable name.
   - No INI settings will engage the behavior.
   - No warnings or notices will be emitted.
   - A polyfill will be made available to emulate that original behavior.
   - Applications requiring name mangling shall invoke the polyfill during
   bootstrap phase.

https://wiki.php.net/rfc/on_demand_name_mangling

---

## #106218 — Zeev Suraski — 2019-07-16T14:13:34+00:00

URL: https://externals.io/message/106213#106218

> 
>
> > […]
> in
> > […]
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> > […]
> it.
> > […]
>
> I've readied the proposal for formal discussion. As proposed:
>
>    - PHP 8.0 will no longer mangle variable names in any super-global.
>    - The changelog will recommend auditing super-global access for mangled
>    names, and replacing with the actual variable name.
>    - No INI settings will engage the behavior.
>    - No warnings or notices will be emitted.
>    - A polyfill will be made available to emulate that original behavior.
>    - Applications requiring name mangling shall invoke the polyfill during
>    bootstrap phase.
>
> https://wiki.php.net/rfc/on_demand_name_mangling


I think it looks good and well thought-through.  The only thing I'd add is
having the userland polyfill function implementation available/referenced
in the Upgrade notes, so that folks can get it without Composer (in
addition of having it available in Composer).  I suspect the ones who'd
actually won't to use it are quite likely to not be Composer users.

Zeev

---

## #106223 — Nikita Popov — 2019-07-16T18:39:03+00:00

URL: https://externals.io/message/106213#106223

> 
>
> > […]
> in
> > […]
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> > […]
> it.
> > […]
>
> I've readied the proposal for formal discussion. As proposed:
>
>    - PHP 8.0 will no longer mangle variable names in any super-global.
>    - The changelog will recommend auditing super-global access for mangled
>    names, and replacing with the actual variable name.
>    - No INI settings will engage the behavior.
>    - No warnings or notices will be emitted.
>    - A polyfill will be made available to emulate that original behavior.
>    - Applications requiring name mangling shall invoke the polyfill during
>    bootstrap phase.
>
> https://wiki.php.net/rfc/on_demand_name_mangling


Can you please start a new [RFC] thread for this?

Nikita

---

## #106229 — Nicolas Grekas — 2019-07-18T07:08:05+00:00

URL: https://externals.io/message/106213#106229

Le mar. 16 juil. 2019 à 09:51, Nikita Popov <nikita.ppv@gmail.com> a écrit :

> On Tue, Jul 16, 2019 at 3:40 AM Arnold Daniels <
> arnold.adaniels.nl@gmail.com>
> wrote:
>
> > […]
> converted
> > […]
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> ).
> > […]
> serves
> > […]
>
> This has been discussed a few times already, and I think that everyone
> agrees that this behavior should go, but not necessarily on the migration
> path. There is an RFC here:
> https://wiki.php.net/rfc/on_demand_name_mangling
> I think that the latest version of that RFC, that basically proposes to
> drop the behavior and tell people to use a polyfill is fine.
>


The RFC doesn't tell about `parse_str()`, while this is the userland variant
of this.
I think it could be useful to make parse_str accept a third argument
starting with PHP 7.4!
That would allow userland code to opt-in for the new behavior asap, and
would provide the core implementation for ppl that want to keep the current
behavior for PHP8.

Makes sense?

Nicolas

---

## #106232 — Rasmus Schultz — 2019-07-18T10:08:36+00:00

URL: https://externals.io/message/106213#106232

> 
>
> > […]
> in
> > […]
> https://php.net/manual/en/language.variables.external.php#language.variables.external.dot-in-names
> > […]
> it.
> > […]
>
> I've readied the proposal for formal discussion. As proposed:
>
>    - PHP 8.0 will no longer mangle variable names in any super-global.
>    - The changelog will recommend auditing super-global access for mangled
>    names, and replacing with the actual variable name.
>    - No INI settings will engage the behavior.
>    - No warnings or notices will be emitted.
>    - A polyfill will be made available to emulate that original behavior.
>    - Applications requiring name mangling shall invoke the polyfill during
>    bootstrap phase.
>
> https://wiki.php.net/rfc/on_demand_name_mangling


What about libraries that need to support both PHP 7 and 8? Many libraries
will likely need to, potentially for a long time.

How will these libraries be able to detect whether the names have been
mangled or not? Libraries that "unmangle" run the risk of "unmangling"
names that aren't actually mangled, and could end up mangling them instead.

This is a particular concern with the proposed polyfill - if there's a
polyfill that mangles the names, you can't just use something like
php_version() to check if it's version 8, since the polyfill could have
been applied.

Maybe consider adding something like $_SERVER["REAL_HEADER_NAMES"] which,
if set, will indicate the names have not been mangled? The polyfill could
then unset() this value - it could even check first if the names are
already non-mangled, whether this is because it's running under PHP 8,
because the polyfill gets bootstrapped twice (which it'll probably need to
check somehow anyway) or because somebody else polyfilled the same change
in some other way.

---

## #106238 — Dan Ackroyd — 2019-07-18T14:27:50+00:00

URL: https://externals.io/message/106213#106238

>
> What about ...

Although there might be real problems for this, please can you
describe a concrete problem that will occur, in a library people use,
rather than a vague possible problem?

For most framework users, all of the request variables are only
accessed through either a PSR7 request object or their framework
specific equivalent, and the problem of mangling/demangling can be
solved there. So for most people this isn't going to be a problem imo.

Without a clear description of what the problem is, coming up with
solutions is not an effective exercise.

cheers
Dan
Ack

---

## #106240 — Rasmus Schultz — 2019-07-18T20:36:16+00:00

URL: https://externals.io/message/106213#106240

> 
> > […]
>
> Although there might be real problems for this, please can you
> describe a concrete problem that will occur, in a library people use,
> rather than a vague possible problem?
>

Well, both underscores and hyphens are permitted in header names - so a
library that replaces underscores with hyphens potentially mangles real
header names. (Mangling and unmangling are both lossy operations.)


> For most framework users, all of the request variables are only
> accessed through either a PSR7 request object or their framework
> specific equivalent, and the problem of mangling/demangling can be
> solved there.
>

Yes, that's my concern - if they don't know whether the names are already
mangled or not, they might apply the unmangling, unintentionally mangling
actual valid header names.

Besides also wasting some CPU time - no point in processing header-names if
they're already properly formatted.

Mainly, all I'm suggesting is that there be some way to tell if the names
were either never mangled, or have already been unmangled, so we can avoid
single or multiple (redundant and/or lossy) mangling/unmangling operations
in the polyfill and PSR-7 libraries.

Since this has to do with $_SERVER, it seems natural to keep it in
$_SERVER["REAL_HEADER_NAMES"], which would be set to true on PHP 8.

So in the polyfill:

    if (isset($_SERVER["REAL_HEADER_NAMES"])) {
        // mangle names...
        unset($_SERVER["REAL_HEADER_NAMES"]);
    }

And in the PSR-7 libraries:

    if (isset($_SERVER["REAL_HEADER_NAMES"])) {
        // use names as is
    } else {
        // unmangle names
    }

This is just an example - I'm indifferent as to the name and location of
this value.

Someone suggested using a constant, but you can't unset a constant - for
the polyfill and PHP 8 both to be seen by a PSR-7 library as having real
header names, the polyfill needs to be able to clear that flag. (With a
constant, you'd need an additional check against php_version() - just
trying to keep this as simple as possible.)

---

## #106241 — lauri.kentta@gmail.com — 2019-07-19T19:37:12+00:00

URL: https://externals.io/message/106213#106241

> PHP replaces dots with underscores for $_GET, $_POST and $_COOKIE.
> Is there a good reason to keep this behavior in PHP 8?
> 

There's a BC break that should be noted:

<input type=image name=i> produces i.x=1&i.y=2

Since the dots can't be changed with HTML, this would then require 
different code to support both PHP 7 and 8.

Also, now that we're at it, what about the following:

i[].x=1 currently produces ['i' => [0 => '1']], losing the x.

i[x].y=1&i[x].z=2 produces ['i' => ['x' => '2']].

Maybe something to be done to address these cases?

-- 
Lauri Kenttä

---

## #106242 — Andrea Faulds — 2019-07-19T22:44:22+00:00

URL: https://externals.io/message/106213#106242

Hi all,

Rasmus Schultz wrote:
> 
> What about libraries that need to support both PHP 7 and 8? Many libraries
> will likely need to, potentially for a long time.
> 
> How will these libraries be able to detect whether the names have been
> mangled or not? Libraries that "unmangle" run the risk of "unmangling"
> names that aren't actually mangled, and could end up mangling them instead.
> 
> This is a particular concern with the proposed polyfill - if there's a
> polyfill that mangles the names, you can't just use something like
> php_version() to check if it's version 8, since the polyfill could have
> been applied.
> 
> Maybe consider adding something like $_SERVER["REAL_HEADER_NAMES"] which,
> if set, will indicate the names have not been mangled? The polyfill could
> then unset() this value - it could even check first if the names are
> already non-mangled, whether this is because it's running under PHP 8,
> because the polyfill gets bootstrapped twice (which it'll probably need to
> check somehow anyway) or because somebody else polyfilled the same change
> in some other way.
> 
Years ago I also wanted to remove the name mangling, but for 
backwards-compatibility reasons I think we should make it as easy as 
possible to migrate.

My preferred solution would be to add a new built-in function that 
re-does the mangling exactly as it used to be done. It would be no great 
maintenance burden on us to maintain such a function for the future, 
but it would avoids userland having to reimplement it multiple times and 
less performantly or perhaps with bugs.

Imagine:

   array php_bc_mangle_request_vars(array $input);

Then an app relying on the legacy behaviour could do this in its 
index.php and breathe easy:

   $_GET = php_bc_mangle_request_vars($_GET);
   $_POST = php_bc_mangle_request_vars($_POST);
   // etc

Or for example, something using some form of Request object that didn't 
do de-mangling could use this function on its $post array.

What does everyone think?

Andrea

---

## #106270 — Stanislav Malyshev — 2019-07-23T22:52:34+00:00

URL: https://externals.io/message/106213#106270

Hi!

> My preferred solution would be to add a new built-in function that
> re-does the mangling exactly as it used to be done. It would be no great
> maintenance burden on us to maintain such a function for the future, but
> it would avoids userland having to reimplement it multiple times and
> less performantly or perhaps with bugs.

That looks like good idea. If we mention it in UPGRADING, that should
make it easier to migrate for people that for one reason or another
still rely on the old ways.
One use cause affected may be image buttons (if anyone still uses them?)
since there usage of .x and .y is standard.
-- 
Stas Malyshev
smalyshev@gmail.com

---

## #106271 — Claude Pache — 2019-07-24T00:03:44+00:00

URL: https://externals.io/message/106213#106271

> Le 24 juil. 2019 à 00:52, Stanislav Malyshev <smalyshev@gmail.com> a écrit :
> 
> Hi!
> 
> > […]
> 
> That looks like good idea. If we mention it in UPGRADING, that should
> make it easier to migrate for people that for one reason or another
> still rely on the old ways.
> One use cause affected may be image buttons (if anyone still uses them?)
> since there usage of .x and .y is standard.
> -- 
> Stas Malyshev
> smalyshev@gmail.com <mailto:smalyshev@gmail.com>

An alternative way to deal with either mangled or unmangled key names is: 
($_GET["foo.x"] ?? $_GET["foo_x"])

—Claude
