PHP global scope and variable initialization - php

Simple question - I'm working with someone else's code and thus would break update-ability if I modify code outside what I'm working on. I'm just wondering in PHP if initialization is implied with the 'global' keyword inside of a function. i.e. is...
// some code
function myFunc() {
global $foo;
}
// other code
reasonably similar to....
// some code
$foo = ""; // any initialization value
function myFunc() {
global $foo;
}
// other code
I prefer to initialize variables in the base scope in which they are used, but as mentioned, that would require me to change the external code in this case.

The global statement merely states that when the current function refers to the variable, it accesses it in the global scope rather than the local scope. It doesn't have any effect on the variable's value by itself.
In other words, it tells PHP that any reference to $foo within that function should be treated equivalent to $GLOBALS['foo']. Assigning it will assign the global variable, and reading from it will access the global variable.

Related

Can global variables be created with the keyword global and through a superglobal variable within a function in PHP?

I have heard using global variables is not good, however I am just trying to understand how the PHP language works. I am a beginner in the coding world.
Why can global variables be created within functions? Whether it is through the use of the global keyword or through a superglobal variable. I thought these two actions were used to access global variables in a function. I thought the only way you can create a global variable is to create it outside a function; in the global scope. I have looked at many different websites including w3schools.com and php.net
This is just some simple code I created to try and understand the way global variables work with functions:
<?php
function sample1() {
global $a;
echo $a = "this ";
}
sample1();
function sample2() {
echo $GLOBALS['$b'] = "is ";
}
sample2();
function sample3() {
global $c;
$c = "an ";
}
sample3();
echo $c;
function sample4() {
$GLOBALS['$d'] = "example ";
}
sample4();
echo $GLOBALS['$d'];
?>
This is the result of the code:
this is an example
All of the code works, but I don't understand how I created a global variable on any of these blocks of code? The global variables were not created outside of the functions. How can they be created inside of a function? What am I missing? Any response is appreciated - If possible, please keep the answer simple - I would like to discuss this further in the comment section, because I'm sure I will have follow up questions - Thank you
Variables can be created in the global scope in the two ways you just did - there's nothing saying that a function can't create (or change) a variable in the global scope - WHEN you explicitly ask for it through $GLOBALS or the global keyword.
The issue is that your belief "I thought the only way you can create a global variable is to create it outside a function; in the global scope." is not an exact statement. When you're using $GLOBALS and global, you're referring to the global scope. You're introducing a reference to the global scope inside your function.
With global you're in effect linking the local reference to the global reference, while with $GLOBALS you're explicitly referencing the global scope (which internally inside PHP can be introduced to the local scope in the same way).
In that case you're explicitly saying "I want this variable to be available in the global scope, make it so!" and PHP does what you're asking it to. This behaviour differ between languages, but as you've discovered for PHP, it's allowed.
It's not something I would recommend using in any way - it makes your code very hard to follow and argue around, so consider it an esoteric detail.

PHP get_defined_vars() doesn't print superglobals inside function

I'm working through debugging some legacy code, and want to use a pre-built function that is essentially a wrapper for get_defined_vars().
Running this code directly in the calling file prints an array of variables as expected:
print_r(get_defined_vars());
However, wrapping this in a simplified version of my function prints an empty array:
function debugAllVars() {
print_r(get_defined_vars());
}
debugAllVars();
Regardless of the scope, I would have expected "superglobal" variables such as $_POST to be present in the output.
Why is the output completely empty?
get_defined_vars() prints all variables in the "symbol table" of the scope where it is called. When you try to wrap it as debugAllVars, you introduce a new scope, which has a new symbol table.
For a standalone function like this, the symbol table consists of:
the function's parameters
any global variables imported into the current scope using the global keyword
any static variables declared in the current scope with the static keyword (even if not assigned a value)
any variables implicitly declared by assigning a value to them
any variables implicitly declared by taking a reference to them (e.g. $foo = &$bar would implicitly declare $bar if not already defined; $foo = $bar would not)
Notably, this list does not include the superglobals, such as $_GET, $_POST, and $GLOBALS. If you run get_defined_vars() in global scope (i.e. outside any function), you will see that these are present in the symbol table there, which is also what the magic variable $GLOBALS points to. So, why are they not present in every scope, and how can we use them if they're not?
For this, we need to dig into the internals of the implementation, where these variables are referred to as "auto-globals" rather than "superglobals".
The answer to why is performance: the naive implementation of an "auto-global" would be one that acted as though every function automatically had a line at the top reading global $_GET, $_POST, ...;. However, this would mean copying all those variables into the symbol table before every function was run, even if they weren't used.
So instead, these variables are special-cased in the compiler, while converting your PHP code into the internal "opcodes" used by the VM which executes the code.
Using a source code browser, we can see how this works.
The key function is zend_is_auto_global in zend_compile.c (taken from current master, effectively PHP 7.2):
zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
{
zend_auto_global *auto_global;
if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
if (auto_global->armed) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name);
}
return 1;
}
return 0;
}
Here, name is the name of a variable, and CG means "compiler globals", so the main job of this function is to say "if the variable name given is in a compiler-global hash called auto_globals, return 1". The additional call to auto_global_callback allows the variable to be "lazy loaded", and only populated when it is first referenced.
The main usage of that function appears to be this conditional, in zend_compile_simple_var_no_cv:
if (name_node.op_type == IS_CONST &&
zend_is_auto_global(Z_STR(name_node.u.constant))) {
opline->extended_value = ZEND_FETCH_GLOBAL;
} else {
opline->extended_value = ZEND_FETCH_LOCAL;
}
In other words, if the variable name you referenced is in the list of superglobals, the compiler switches the opcode into a different mode, so that when it is executed, it looks up the variable globally rather than locally.
get_defined_vars gets all variables defined in the scope that it's called in. Your debugAllVars function introduces a new scope, so get_defined_vars will at most give you all variables within debugAllVars. It cannot give you variables from the caller's scope.
Also see Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?.

global variables from one function to another

Lets say I have this:
function myFunc()
{
global $distinct_variable;
die ($distinct_variable);
}
function anotherFunc()
{
$distinct_variable = 'Hello World';
myFunc();
}
anotherFunc();
For anotherFunc() to correctly show 'Hello World', it must be written like this
{
global $distinct_variable;
$distinct_variable = 'Hello World';
myFunc();
}
Now it will show the message, but why must I global $distinct_variable; in anotherFunc() since it is a global in myFunc() which is within anotherFunc()
Yes, I know that variables inside functions won't go outside of them, but I was thinking it should have worked...
Could someone explain why isn't it working?
Thanks.
Thank you for your answers, I get it now :)
A global variable is exactly that - it exists in the GLOBAL scope ONLY.
Everything in PHP (except superglobals) exist in only one scope - be that the global scope, or the scope of a function/method. Scope does not cascade - so just because you have a variable in an "outer" function does not make it available to an "inner" function.
Similarly, global fetches the variables defined in the GLOBAL scope only (the top-most scope), not simply "the scope above this one, from which I was called". This is what you tried to do, but it absolutely will not work. This level of finer-grained control is what function arguments/return values are for.
Each function has its own symbol table. There is also a global symbol table. Just because one function is being called from within another doesn't mean that the variables declared global in one are global in the other, or inherited from the other. They still refer to the variable in the "local" symbol table by default.
Doing global $somevar; echo $somevar boils down to echo $GLOBALS['somevar'];. That $GLOBALS superglobal does not include variables that were defined inside a function: only truly 'global' vars, which exist at the top level of the script.

Are variables outside functions global variables?

<?php
$foo = 1;
function meh(){
// <-- $foo can't be accessed
}
It doesn't look like a global variable. However, does it have disadvantages like global stuff if it's outside the function?
All variables defined outside any function are declared in global scope. If you want to access a global variable you have two choices:
Use the global keyword
<?php
$a = 1;
$b = 2;
function Sum()
{
global $a, $b;
$b = $a + $b;
}
?>
Or use the $GLOBALS
<?php
$a = 1;
$b = 2;
function Sum()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
?>
Read more at http://php.net/manual/en/language.variables.scope.php
Yes. They can be accessed from any location, including other scripts. They are slightly better as you have to used the global keyword to access them from within a function, which gives more clarity as to where they are coming from and what they do.
The disadvantages of global variables apply, but this doesn't instantly make them evil as is often perceived in some OO languages. If they produce a good solution that's efficient and easily understandable, then you're fine. There are literally millions of succesful PHP projects that use global variables declared like this. The biggest mistake you can make is not using them and making your code even more complicated when it would have been perfectly fine to use them in the first place. :D
<?php
$foo = 1;
function meh(){
global $foo;
// <-- $foo now can be accessed
}
?>
Outside of the function is sorta like global scope (when compared to C-like languages), but you have to do one thing to allow access to the var within a function:
function meh(){
global $foo;
// $foo now exists in this scope
}
In your example $foo gets created as variable in the global scope. (Unless your shown script was included() from within another functions/methods scope.)
PHP doesn't have real global variables. You have to manually alias it using the global $foo; statement to access them. (Also the "anything global is bad" advise is just that, bad advise.)
If I understand your question correctly, there really shouldn't be a problem. Unless you declare a variable as a global, it will been limited to the scope in which it is declared, in this case whatever php file the above code is defined in. You could declare another variable $foo in meh() and it would be independent of the $foo defined outside.

global variables in php not working as expected

I'm having trouble with global variables in php. I have a $screen var set in one file, which requires another file that calls an initSession() defined in yet another file. The initSession() declares global $screen and then processes $screen further down using the value set in the very first script.
How is this possible?
To make things more confusing, if you try to set $screen again then call the initSession(), it uses the value first used once again. The following code will describe the process. Could someone have a go at explaining this?
$screen = "list1.inc"; // From model.php
require "controller.php"; // From model.php
initSession(); // From controller.php
global $screen; // From Include.Session.inc
echo $screen; // prints "list1.inc" // From anywhere
$screen = "delete1.inc"; // From model2.php
require "controller2.php"
initSession();
global $screen;
echo $screen; // prints "list1.inc"
Update:
If I declare $screen global again just before requiring the second model, $screen is updated properly for the initSession() method. Strange.
Global DOES NOT make the variable global. I know it's tricky :-)
Global says that a local variable will be used as if it was a variable with a higher scope.
E.G :
<?php
$var = "test"; // this is accessible in all the rest of the code, even an included one
function foo2()
{
global $var;
echo $var; // this print "test"
$var = 'test2';
}
global $var; // this is totally useless, unless this file is included inside a class or function
function foo()
{
echo $var; // this print nothing, you are using a local var
$var = 'test3';
}
foo();
foo2();
echo $var; // this will print 'test2'
?>
Note that global vars are rarely a good idea. You can code 99.99999% of the time without them and your code is much easier to maintain if you don't have fuzzy scopes. Avoid global if you can.
global $foo doesn't mean "make this variable global, so that everyone can use it". global $foo means "within the scope of this function, use the global variable $foo".
I am assuming from your example that each time, you are referring to $screen from within a function. If so you will need to use global $screen in each function.
You need to put "global $screen" in every function that references it, not just at the top of each file.
If you have a lot of variables you want to access during a task which uses many functions, consider making a 'context' object to hold the stuff:
//We're doing "foo", and we need importantString and relevantObject to do it
$fooContext = new StdClass(); //StdClass is an empty class
$fooContext->importantString = "a very important string";
$fooContext->relevantObject = new RelevantObject();
doFoo($fooContext);
Now just pass this object as a parameter to all the functions. You won't need global variables, and your function signatures stay clean. It's also easy to later replace the empty StdClass with a class that actually has relevant methods in it.
You must declare a variable as global before define values for it.
The global scope spans included and required files, you don't need to use the global keyword unless using the variable from within a function. You could try using the $GLOBALS array instead.
It is useless till it is in the function or a class. Global means that you can use a variable in any part of program. So if the global is not contained in the function or a class there is no use of using Global

Categories