Question about `global` variable declaration

php.internals

Kosit Supanyo

6 years ago
Hi Internals I'm working on my new proposals and I've found weirdness of global variable declaration in zend_language_parser.y. global_var: simple_variable { $$ = zend_ast_create(ZEND_AST_GLOBAL, zend_ast_create(ZEND_AST_VAR, $1)); } ; Above grammer allows something like this... global $$x; global $$$y; global $$$$z; global ${'abc'}; global $$$$$$$$$${random_int(0, PHP_INT_MAX)}; What's the propose of allowing this? And is there anyone out there knowing and using it? If not, should this be changed to allow only T_VARIABLE to make it consistent with `static` variable declaration? Regards

Dan Ackroyd

6 years ago
Hi Kosit, On Sat, 21 Sep 2019 at 10:56, Kosit Supanyo <webdevxp.com@gmail.com> wrote:
> > global $$x; > global $$$y; > global $$$$z; > global ${'abc'}; > global $$$$$$$$$${random_int(0, PHP_INT_MAX)};
I have found the form `global ${'abc'};` useful in the past to work around the limits on what PHP can parse as variable names, to allow naming global settings to match how I like to write them in config files e.g. 'image.upload.retry_attempts'. I would be very surprised if there was no codebase in existence that didn't use the other forms, for better or worse.
> If not, should this be changed to ...
For changes like this, the conversation almost certainly needs to start by stating a clear problem something is causing, and then lead on to why doing a suggested solution is the right thing to do. Although this might be a small inconsistency in the language, by itself, I can't see it causing much harm, except maybe for performance optimisation as trying to analyze what variables are being used in the code is hard. cheers Dan Ack

Nikita Popov

6 years ago
On Sat, Sep 21, 2019 at 11:56 AM Kosit Supanyo <webdevxp.com@gmail.com> wrote:
> Hi Internals > > I'm working on my new proposals and I've found weirdness of global variable > declaration in zend_language_parser.y. > > global_var: > simple_variable > { $$ = zend_ast_create(ZEND_AST_GLOBAL, > zend_ast_create(ZEND_AST_VAR, $1)); } > ; > > Above grammer allows something like this... > > global $$x; > global $$$y; > global $$$$z; > global ${'abc'}; > global $$$$$$$$$${random_int(0, PHP_INT_MAX)}; > > What's the propose of allowing this? And is there anyone out there knowing > and using it? If not, should this be changed to allow only T_VARIABLE to > make it consistent with `static` variable declaration? > > Regards >
Some grep results: sources/adodb/adodb-php/session/adodb-session.php 676: global $$var; 697: global $$var; sources/adodb/adodb-php/session/adodb-session2.php 719: global $$var; 740: global $$var; sources/adodb/adodb-php/session/old/adodb-cryptsession.php 189: global $$var; sources/adodb/adodb-php/session/old/adodb-session.php 300: global $$var; sources/adodb/adodb-php/session/old/adodb-session-clob.php 269: global $$var; sources/wp-cli/wp-cli/php/WP_CLI/Runner.php 1177: global ${$key}; sources/apache/log4php/src/main/php/pattern/LoggerPatternConverterSuperglobal.php 71: global ${$this->name}; We could deprecate this in favor of $GLOBALS, though as Dan said, the motivation is not quite clear right now. Nikita

Kosit Supanyo

6 years ago
Hi Dan and Internals Sorry Dan, I forgot to include @Internals in previous reply so let me resend this again. Thank you for your reply. I see, but in that case it can be done with `$GLOBALS['abc']` right? So I don't see any benefits of allowing those forms, they're just another inconsistency that should not exist from the beginning. Yes, it does no harms but if nobody is really using it at all, is it good to remove this inconsistency? Or to make it really useful, why not just allow assignment like: global ${'abc'} = $someValue; Just my 2 cents. Regards On Sat, Sep 21, 2019 at 5:52 PM Nikita Popov <nikita.ppv@gmail.com> wrote:

Nikita Popov

6 years ago
On Sat, Sep 21, 2019 at 12:58 PM Kosit Supanyo <webdevxp.com@gmail.com> wrote:
> Hi Dan and Internals > > Sorry Dan, I forgot to include @Internals in previous reply so let me > resend this again. > > Thank you for your reply. I see, but in that case it can be done with > `$GLOBALS['abc']` right? So I don't see any benefits of allowing those > forms, they're just another inconsistency that should not exist from the > beginning. Yes, it does no harms but if nobody is really using it at all, > is it good to remove this inconsistency? Or to make it really useful, why > not just allow assignment like: > > global ${'abc'} = $someValue; > > Just my 2 cents. > > Regards >
global $x; is a shorthand for $x =& $GLOBALS['x']; global ${$x}; is a shorthand for ${$x} =& $GLOBALS[$x]; I don't think this syntax is inconsistent so long as PHP supports the syntax ${$x} for variables in general. The idea of a "global ${'abc'} = $someValue;" syntax doesn't seem to have a relation to the ${} form in particular. A simple "global $var = $someValue" is currently not supported either. That's because "global $var" simply imports a global variable into the local scope. You would instead write this as "global $var; $var = $someValue;". Nikita

Kosit Supanyo

6 years ago
I understand your point but inconsistency in my sense is syntactical By comparing to other declaration syntax like `var`, `static`, 'public` an others. They allow only T_VARIABLE but `global` is different. And there's another way to archive the same goal through `$GLOBALS`, that's why I see it as inconsistency. P.S. I wrote this not because I want to convince you to make any change but just to explain my point. Cheers On Sat, Sep 21, 2019 at 6:24 PM Nikita Popov <nikita.ppv@gmail.com> wrote:

Zeev Suraski

6 years ago
On Sat, Sep 21, 2019 at 3:09 PM Kosit Supanyo <webdevxp.com@gmail.com> wrote:
> I understand your point but inconsistency in my sense is syntactical By > comparing to other declaration syntax like `var`, `static`, 'public` an > others. They allow only T_VARIABLE but `global` is different. And there's > another way to archive the same goal through `$GLOBALS`, that's why I see > it as inconsistency. >
Even though we're dealing with archeology here - this really isn't an inconsistency but intended behavior. Unlike var, public, static and others - 'global' is not a declaration of class structure, but a way to access global variables. In the same way it sometimes makes sense to access variables indirectly ($$foo), it may sometimes make sense to access global variables indirectly (global $$foo). It allows for both creation and access of global variables. It doesn't sound very useful or practical to provide that ability for the creation of dynamic class properties, which is why it's not available for var/public/static/etc. Zeev

Kosit Supanyo

6 years ago
> > Unlike var, public, static and others - 'global' is not a declaration of > class structure, but a way to access global variables.
I know it is not and I think almost everyone knows that. As I said, I came up with this by comparing to other declarations syntactically not functionally, it is inconsistent in that way. I don't know how many PHP developers out there know `global` can take variable variables but I my guess is, very very little because there's no information about this behavior of `global` in PHP manual https://www.php.net/manual/en/language.variables.scope.php and I'd never seen those forms of `global` in any projects/articles before. Cheers On Sat, Sep 21, 2019 at 9:26 PM Zeev Suraski <zeev@php.net> wrote:

Zeev Suraski

6 years ago
On Sat, Sep 21, 2019 at 6:18 PM Kosit Supanyo <webdevxp.com@gmail.com> wrote:
> Unlike var, public, static and others - 'global' is not a declaration of >> class structure, but a way to access global variables. > > > I know it is not and I think almost everyone knows that. As I said, I came > up with this by comparing to other declarations syntactically not > functionally, it is inconsistent in that way. I don't know how many PHP > developers out there know `global` can take variable variables but I my > guess is, very very little because there's no information about this > behavior of `global` in PHP manual > https://www.php.net/manual/en/language.variables.scope.php and I'd never > seen those forms of `global` in any projects/articles before. >
I think you're raising two separate points: 1. The global statement is inconsistent with other similar statements. 2. It's not widely used and we should consider deprecating this behavior. Re: #1 - even though it may look similar, the global statement is fundamentally different from public/private/static and friends. It's not really a declaration - it's like Nikita said is a simple equivalent for writing $foo = &$GLOBALS['foo'] - and as such, is a runtime statement as opposed to a compile-time declaration like the others. So despite the superficial similarities, the differences between the two justify different behavior/allowed syntax. Re: #2 - the fact it's not documented is a fair point - but I'm not sure that in itself is cause for anything other than perhaps adding a quick note in the docs. People familiar with PHP's variable-variables functionality ( https://www.php.net/manual/en/language.variables.variable.php) will not find this behavior as inconsistent or otherwise surprising, I think. It does appear to be mentioned in some places (e.g. the O'Reilly PHP Cookbook, https://www.oreilly.com/library/view/php-cookbook/1565926811/ch06s12.html). I doubt there'll be a big impact if we were to deprecate this behavior - it doesn't appear very mainstream (and there's a simple workaround available through $GLOBALS) - but I don't see any gain to be had either. Zeev