Hi Internals,
I'd like to open up a discussion around the implementation of a new
functionality: 'import of variables'.
This functionality would allow to create a new 'use vars' keyword in order to can use( or cannot use ) global variables in local scope( of current file ).
I think the best is a example:
<?php
$a = 1;
$b = 2;
$c = 3;
include __DIR__.'/without_import.php';
include __DIR__.'/all_import.php';
include __DIR__.'/none_import.php';
include __DIR__.'/some_vars.php';
include __DIR__.'/global_in_function.php';
without_import.php
<?php
echo $a; //1
echo $b; //2
$c = 'any value'; //replace value in global var
all import.php
<?php
use vars all;
echo $a; //1
echo $b; //2
$c = 'other value'; //replace value in global var
none_import.php
<?php
use vars none;
echo $a; //Warning: undefined var $a
echo $b; //Warning: undefined var $b
$c = 'other value'; //assign value to local var
some_vars.php
<?php
use vars $a, $c, $d; //Warning: undefined var $d
echo $a; //1
echo $b; //Warning: undefined var $b
$c = 'a value'; //replace value in global var
global_in_function.php
<?php
use vars $a, $c;
function hello() {
global $a, $b, $c;
echo $a; //1
echo $b; //null.
$c = 'end value'; //replace value in global var
}
hello();
In a project with a lot of global vars( like WordPress ) this functionality avoids conflicts and easy replacements of values in main global vars.
Regards
Manuel Canga
Hi Internals,
I'd like to open up a discussion around the implementation of a new
functionality: 'import of variables'.This functionality would allow to create a new 'use vars' keyword in order to can use( or cannot use ) global variables in local scope( of current file ).
Right now, PHP has no notion of "file scope", and making that the
default would be a huge compatibility break. The "use vars none"
variant that opts out of the global scope might be possible, but at
that point, you can just use the common JS trick of wrapping your code
in a function and immediately running it:
<?php
(function() {
global $a, $c, $d;
echo $a; //1
echo $b; //Warning: undefined var $b
$c = 'a value'; //replace value in global var
})();
The last example, where the function uses "global" but only gets the
globals if they're also "used" in the current file, seems like it would
make more sense using a class, a static method, and some private static
variables, since right now we don't think of a function as "belonging
to" a file in the same way it would belong to a class.
Regards,
--
Rowan Tommins (né Collins)
[IMSoP]
Hi Internals,
This functionality would allow to create a new 'use vars' keyword in order to can use( or cannot use ) global variables in local scope( of current file ).
To be clear: The variables in the top-level scope depend on what has require()d/include()d a file.
The top-level scope starts off as being global, but if a file is required from within a function/method/closure (e.g. the autoloader closure), then the top-level scope in the require()'d file uses variables (e.g. $this) from whatever context called require().
It may be possible to use a declare syntax, e.g. declare(used_variables='all') for 'all'
, null
, ['var1', 'var2']
, etc.
- Otherwise, you face the issue of where
use vars
should be allowed, what happens if there's a statement beforeuse vars
, etc.
I can see this as having some use cases, such as in configuration files or files used for bootstrapping.
For example,
<?php
declare(used_variables=null);
$api_base = IS_PRODUCTION ? 'https://example.com/api/' : 'http://localhost/api';
do_stuff();
return [
// long config array
'url_new' => "$api_base/new",
'url_all' => "$api_base/all",
];
This feature (ignoring the question of syntax) would ensure that people reading the file knew that $api_base was not modified by other files
and that other files did not read local variables created within a configuration/bootstrapping file in unexpected ways,
which is a fairly common issue in some web apps I've worked on.
Opcache would also do a better job at optimizing code if it knew which variables in a top-level scope couldn't be modified.
That being said, there's been opposition to extensions to the language that add functionality that can be implemented in other ways, as in Rowan's comment,
but peoples opinions depend on the specifics of the proposal
(e.g. match
was added and was more performant than chained conditionals or switch).
As Rowan said, there are ways to reimplement this:
- Wrapping the config file or bootstrapping file in a closure, global function, or class method
-
function safe_require_once(string $path, $vars = []) { extract($vars); require($path); }
from the caller, to limit what variables are passed in. IDEs/tooling would be worse at telling you if a file name had a typo, though.
Regards,
- Tyson
I suggests to make something like Node does: import "file.php" ($a, $b) so
$a and $b must be extracted from file.php context. All other variables
should be ignored.
Or, to avoid create more complexity and possible new keywords to import
syntax, maybe create a new function:
importx(string $file, ?array $extract = null) and requirex(...) (importx
and requirex is only pseudo)
Em dom, 9 de ago de 2020 11:42, tyson andre tysonandre775@hotmail.com
escreveu:
Hi Internals,
This functionality would allow to create a new 'use vars' keyword in
order to can use( or cannot use ) global variables in local scope( of
current file ).To be clear: The variables in the top-level scope depend on what has
require()d/include()d a file.
The top-level scope starts off as being global, but if a file is required
from within a function/method/closure (e.g. the autoloader closure), then
the top-level scope in the require()'d file uses variables (e.g. $this)
from whatever context called require().It may be possible to use a declare syntax, e.g.
declare(used_variables='all') for'all'
,null
,['var1', 'var2']
, etc.
- Otherwise, you face the issue of where
use vars
should be allowed,
what happens if there's a statement beforeuse vars
, etc.I can see this as having some use cases, such as in configuration files or
files used for bootstrapping.
For example,<?php declare(used_variables=null); $api_base = IS_PRODUCTION ? 'https://example.com/api/' : ' http://localhost/api'; do_stuff(); return [ // long config array 'url_new' => "$api_base/new", 'url_all' => "$api_base/all", ];
This feature (ignoring the question of syntax) would ensure that people
reading the file knew that $api_base was not modified by other files
and that other files did not read local variables created within a
configuration/bootstrapping file in unexpected ways,
which is a fairly common issue in some web apps I've worked on.
Opcache would also do a better job at optimizing code if it knew which
variables in a top-level scope couldn't be modified.That being said, there's been opposition to extensions to the language
that add functionality that can be implemented in other ways, as in Rowan's
comment,
but peoples opinions depend on the specifics of the proposal
(e.g.match
was added and was more performant than chained conditionals
or switch).As Rowan said, there are ways to reimplement this:
- Wrapping the config file or bootstrapping file in a closure, global
function, or class methodfunction safe_require_once(string $path, $vars = []) { extract($vars); require($path); }
from the caller, to limit what variables are passed in.
IDEs/tooling would be worse at telling you if a file name had a typo,
though.Regards,
- Tyson
--To unsubscribe, visit: https://www.php.net/unsub.php
Have not tested - just catching up on emails.
To verify: A property defined with a default value of the global does not already do this?
Developer need: I rarely access global variables directly - usually going through a lib or framework. When I do I would probably wrap the access in a trait or method on a class.
Cheers,
Josh
I suggests to make something like Node does: import "file.php" ($a, $b) so
$a and $b must be extracted from file.php context. All other variables
should be ignored.Or, to avoid create more complexity and possible new keywords to import
syntax, maybe create a new function:importx(string $file, ?array $extract = null) and requirex(...) (importx
and requirex is only pseudo)Em dom, 9 de ago de 2020 11:42, tyson andre tysonandre775@hotmail.com
escreveu:Hi Internals,
This functionality would allow to create a new 'use vars' keyword in
order to can use( or cannot use ) global variables in local scope( of
current file ).To be clear: The variables in the top-level scope depend on what has
require()d/include()d a file.
The top-level scope starts off as being global, but if a file is required
from within a function/method/closure (e.g. the autoloader closure), then
the top-level scope in the require()'d file uses variables (e.g. $this)
from whatever context called require().It may be possible to use a declare syntax, e.g.
declare(used_variables='all') for'all'
,null
,['var1', 'var2']
, etc.
- Otherwise, you face the issue of where
use vars
should be allowed,
what happens if there's a statement beforeuse vars
, etc.I can see this as having some use cases, such as in configuration files or
files used for bootstrapping.
For example,<?php declare(used_variables=null); $api_base = IS_PRODUCTION ? 'https://example.com/api/' : ' http://localhost/api'; do_stuff(); return [ // long config array 'url_new' => "$api_base/new", 'url_all' => "$api_base/all", ];
This feature (ignoring the question of syntax) would ensure that people
reading the file knew that $api_base was not modified by other files
and that other files did not read local variables created within a
configuration/bootstrapping file in unexpected ways,
which is a fairly common issue in some web apps I've worked on.
Opcache would also do a better job at optimizing code if it knew which
variables in a top-level scope couldn't be modified.That being said, there's been opposition to extensions to the language
that add functionality that can be implemented in other ways, as in Rowan's
comment,
but peoples opinions depend on the specifics of the proposal
(e.g.match
was added and was more performant than chained conditionals
or switch).As Rowan said, there are ways to reimplement this:
- Wrapping the config file or bootstrapping file in a closure, global
function, or class methodfunction safe_require_once(string $path, $vars = []) { extract($vars); require($path); }
from the caller, to limit what variables are passed in.
IDEs/tooling would be worse at telling you if a file name had a typo,
though.Regards,
- Tyson
--To unsubscribe, visit: https://www.php.net/unsub.php
Hi, Josh. Thanks
---- En dom, 09 ago 2020 21:36:30 +0200 Josh Bruce josh@joshbruce.dev escribió ----
Have not tested - just catching up on emails.
To verify: A property defined with a default value of the global does not already do this?
In functions/methods. In some files can "inherit" gobal vars directly or simply "inherit" local vars of other function.
Developer need: I rarely access global variables directly - usually going through a lib or framework. When I do I would probably wrap the access in a trait or method on a class.
Some frameworks or CMS use view files in PHP like templates.
https://platesphp.com/v3/templates/syntax/#syntax-example
In WordPress case:
"Developers are advised to consider this a Reserved Name List, and not to create local variables with the same names in Plugins or Themes. Under some circumstances, the global variable value will be replaced by the local variable value, causing errors in the WordPress Core that are difficult to diagnose. "
https://codex.wordpress.org/Global_Variables
This could be avoid easily with "use vars none" on the start of each file of theme/plugin.
Regards
Hi, David. Thanks
---- En dom, 09 ago 2020 16:58:41 +0200 David Rodrigues david.proweb@gmail.com escribió ----
I suggests to make something like Node does: import "file.php" ($a, $b) so $a and $b must be extracted from file.php context. All other variables should be ignored.
Or, to avoid create more complexity and possible new keywords to import syntax, maybe create a new function:
importx(string $file, ?array $extract = null) and requirex(...) (importx and requirex is only pseudo)
That is a good idea!. However, in some framworks/CMS you don't have control about include/require. :(
Regards
Hi, Tyson, Thanks.
---- En dom, 09 ago 2020 16:41:44 +0200 tyson andre tysonandre775@hotmail.com escribió ----
Hi Internals,
To be clear: The variables in the top-level scope depend on what has require()d/include()d a file.
The top-level scope starts off as being global, but if a file is required from within a function/method/closure (e.g. the autoloader closure), then the top-level scope in the require()'d file uses variables (e.g. $this) from whatever context called require().
My idea was using 'use vars' not only with global vars but also with vars in context.
It may be possible to use a declare syntax, e.g. declare(used_variables='all') for
'all'
,null
,['var1', 'var2']
, etc.
- Otherwise, you face the issue of where
use vars
should be allowed, what happens if there's a statement beforeuse vars
, etc.
Good point, I don't think about that.
I can see this as having some use cases, such as in configuration files or files used for bootstrapping.
For example,<?php declare(used_variables=null); $api_base = IS_PRODUCTION ? 'https://example.com/api/' : 'http://localhost/api'; do_stuff(); return [ // long config array 'url_new' => "$api_base/new", 'url_all' => "$api_base/all", ];
This feature (ignoring the question of syntax) would ensure that people reading the file knew that $api_base was not modified by other files
and that other files did not read local variables created within a configuration/bootstrapping file in unexpected ways,
which is a fairly common issue in some web apps I've worked on.
Opcache would also do a better job at optimizing code if it knew which variables in a top-level scope couldn't be modified.That being said, there's been opposition to extensions to the language that add functionality that can be implemented in other ways, as in Rowan's comment,
but peoples opinions depend on the specifics of the proposal
(e.g.match
was added and was more performant than chained conditionals or switch).As Rowan said, there are ways to reimplement this:
- Wrapping the config file or bootstrapping file in a closure, global function, or class method
function safe_require_once(string $path, $vars = []) { extract($vars); require($path); }
from the caller, to limit what variables are passed in. IDEs/tooling would be worse at telling you if a file name had a typo, though.
I think in views system( of some frameworks ) or CMS like WordPress. In WordPress, for example, I can do something like this:
index.php
foreach($posts as $post ) {
$post = 'foo';
}
index.php is loaded from CMS. $post is a global variable used in WordPress core. So that, I am crashing WordPress. However, with:
use vars none;
foreach($posts as $post ) {
$post = 'foo';
}
I don't crash my WordPress or any external plugin which can use global vars. My file now is a container( black box ) where my code is isolated.
Regards
Hey Manuel,
Hi Internals,
I'd like to open up a discussion around the implementation of a new
functionality: 'import of variables'.This functionality would allow to create a new 'use vars' keyword in
order to can use( or cannot use ) global variables in local scope( of
current file ).I think the best is a example:
<?php $a = 1; $b = 2; $c = 3; include __DIR__.'/without_import.php'; include __DIR__.'/all_import.php'; include __DIR__.'/none_import.php'; include __DIR__.'/some_vars.php'; include __DIR__.'/global_in_function.php';
without_import.php
<?php echo $a; //1 echo $b; //2 $c = 'any value'; //replace value in global var
all import.php
<?php use vars all; echo $a; //1 echo $b; //2 $c = 'other value'; //replace value in global var
none_import.php
<?php use vars none; echo $a; //Warning: undefined var $a echo $b; //Warning: undefined var $b $c = 'other value'; //assign value to local var
some_vars.php
<?php use vars $a, $c, $d; //Warning: undefined var $d echo $a; //1 echo $b; //Warning: undefined var $b $c = 'a value'; //replace value in global var
global_in_function.php
<?php use vars $a, $c; function hello() { global $a, $b, $c; echo $a; //1 echo $b; //null. $c = 'end value'; //replace value in global var } hello();
In a project with a lot of global vars( like WordPress ) this
functionality avoids conflicts and easy replacements of values in main
global vars.
This looks like what IIFE do already (you can use them today):
require 'something/with/side/effects.php';
(static function () use ($a, $b, & $c) : void {
echo $a; //1
echo $b; //Warning: undefined var $b
$c = 'a value'; //replace value in global var
})();
You can use this right now, and it has the advantage of reporting any
missing symbols right at the time at which the closure is declared.
I tend to use IIFE all the time in procedural code, since they prevent
leaking state into globals ?
Hi, Internals,
Thanks, Marco and also to Rowans, Josh, David and Tyson
I'll use IIFE in order to avoid global conflicts.
Regards
---- En lun, 10 ago 2020 02:16:06 +0200 Marco Pivetta ocramius@gmail.com escribió ----
Hey Manuel,
Hi Internals,
I'd like to open up a discussion around the implementation of a new
functionality: 'import of variables'.This functionality would allow to create a new 'use vars' keyword in
order to can use( or cannot use ) global variables in local scope( of
current file ).I think the best is a example:
<?php $a = 1; $b = 2; $c = 3; include __DIR__.'/without_import.php'; include __DIR__.'/all_import.php'; include __DIR__.'/none_import.php'; include __DIR__.'/some_vars.php'; include __DIR__.'/global_in_function.php';
without_import.php
<?php echo $a; //1 echo $b; //2 $c = 'any value'; //replace value in global var
all import.php
<?php use vars all; echo $a; //1 echo $b; //2 $c = 'other value'; //replace value in global var
none_import.php
<?php use vars none; echo $a; //Warning: undefined var $a echo $b; //Warning: undefined var $b $c = 'other value'; //assign value to local var
some_vars.php
<?php use vars $a, $c, $d; //Warning: undefined var $d echo $a; //1 echo $b; //Warning: undefined var $b $c = 'a value'; //replace value in global var
global_in_function.php
<?php use vars $a, $c; function hello() { global $a, $b, $c; echo $a; //1 echo $b; //null. $c = 'end value'; //replace value in global var } hello();
In a project with a lot of global vars( like WordPress ) this
functionality avoids conflicts and easy replacements of values in main
global vars.This looks like what IIFE do already (you can use them today):
require 'something/with/side/effects.php'; (static function () use ($a, $b, & $c) : void { echo $a; //1 echo $b; //Warning: undefined var $b $c = 'a value'; //replace value in global var })();
You can use this right now, and it has the advantage of reporting any
missing symbols right at the time at which the closure is declared.I tend to use IIFE all the time in procedural code, since they prevent
leaking state into globals ?