0

There is A LOT concerning proper global variables use, and I'm about to request further clarification. Many of the posts dating back 3 years asked, "How do I make variables included in a function, global in scope."

My assumption is that their code looks like this, since no explicit examples were given:

Example 1

#global_vars.php
<?
$my_global_var = "Hello World";
?>

#index.php
<?
function foo ()
{
   include_once ("global_vars.php");
   global $my_global_var;
   print ("my global var = [" . $my_global_var . "]<BR>");
   print ("complete<BR>");
}

foo ();
?>

which outputs:

my global var = [] 
complete

Example 2

Now, if "globals_var.php" is changed to:

<?
global $my_global_var;
$my_global_var = "Hello World";
?>

The results are:

my global var = [Hello World]
complete

Example 3

Now before you write and state that this type of global variable use is not advised, there are practical uses of global variables. And that most global variable are encapsulated in objects as a constant or as a function:

#global_vars.php
<?
class Globals 
{
    const my_global_var = "Hello World";

    public static $my_global_var2 = "Hello World";

    static function my_global_var3 ($newValue = null)
    {
        if (isset ($newValue))
            self::$my_global_var2 = $newValue;

        return (self::$my_global_var2);
    }
}
?>

#index.php
<?
function foo ()
{
    include_once ("global_vars.php");
    print ("my global var = [" . Globals::my_global_var . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3("Hi There") . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("complete<BR>");
}

foo ();
?>

The output is:

my global var = [Hello World]
my global var = [Hello World]
my global var = [Hi There]
my global var = [Hi There]
complete

Example 4

Of course at this point the "include_once" statement could be moved outside the function to get the same results.

#index.php
<?
include_once ("global_vars.php");

function foo ()
{
    print ("my global var = [" . Globals::my_global_var . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3("Hi There") . "]<BR>");
    print ("my global var = [" . Globals::my_global_var3() . "]<BR>");
    print ("complete<BR>");
}

foo ();
?>

The output:

my global var = [Hello World]
my global var = [Hello World]
my global var = [Hi There]
my global var = [Hi There]
complete

Example 5

In this example, the file is included outside the function. Everything works as explained by the PHP.net documentation.

#global_vars.php
<?
$my_global_var = "Hello World";
?>

#index.php
<?
include_once ("global_vars.php");

function foo ()
{
    global $my_global_var;

    print ("my global var = [" . $my_global_var . "]<BR>");
    $my_global_var = "Hi There";
    print ("my global var = [" . $my_global_var . "]<BR>");
}

foo ();
?>

Question ...

Now for my question ... If there is no namespace, why are variables included in Example 1 not to placed in $GLOBALS? And, why are these variables not considered part of the function scope? What's going on here?

Example 1 - GLOBALS / Defined Vars

#index.php
<?

function foo ()
{
    include_once ("global_vars.php");

    global $my_global_var;

    print ("my global var = [" . $my_global_var . "]<BR>");

    print ("<pre>");
    print_r ($GLOBALS);
    print ("</pre>");

    print ("<pre>");
    print_r (get_defined_vars ());
    print ("</pre>");

}

foo ();
?>

The output is:

my global var = []

Array
(
    [_GET] => Array ()
    [_POST] => Array ()
    [_COOKIE] => Array  ( ... )
    [_FILES] => Array ()
    [GLOBALS] => Array
 *RECURSION*
    [my_global_var] => 
)

Array
(
    [my_global_var] => 
)

Example 2 - GLOBALS / Defined Vars

my global var = [Hello World]

Array
(
    [_GET] => Array ()
    [_POST] => Array ()
    [_COOKIE] => Array  ( ... )
    [_FILES] => Array ()
    [GLOBALS] => Array
 *RECURSION*
    [my_global_var] => Hello World
)

Array
(
    [my_global_var] => Hello World
)

Example 6

Based on "@kainaw" answer I have updated Example 1 to help others understand what this would look like based on the examples given. Assume that nothing changed in "global_vars.php", but that in the "index.php" file the global statement preceded the include statement. It is then that "my_gloval_var" is considered by PHP to be a global variable, and initialized as such.

#global_vars.php
<?
$my_global_var = "Hello World";
?>

#index.php
<?
function foo ()
{
   global $my_global_var;

   include_once ("global_vars.php");

   print ("my global var = [" . $my_global_var . "]<BR>");
   print ("complete<BR>");
}

foo ();
?>

which outputs:

my global var = [Hello World] 
complete

The $GLOBALS and Define Vars return the following:

my global var = [Hello World]

Array
(
    [_GET] => Array ()
    [_POST] => Array ()
    [_COOKIE] => Array  ( ... )
    [_FILES] => Array ()
    [GLOBALS] => Array
 *RECURSION*
    [my_global_var] => Hello World
)

Array
(
    [my_global_var] => Hello World
)
E Net Arch
  • 458
  • 5
  • 13
  • 1
    "There is A LOT concerning proper global variables use" There really is not. [Just don't use `global`s](http://stackoverflow.com/questions/11923272/use-global-variables-in-a-class/11923384#11923384). – PeeHaa Dec 31 '14 at 19:21
  • Most of your examples can be answered with PHP does not really have "*global*" variables as such. Everything is in a local scope per default. There's just a shared scope. And all the `global` keyword does is populate/overwrite the local variable table with a reference to said shared scope. – mario Dec 31 '14 at 19:29

1 Answers1

2

The main issue you have is a misunderstanding of what happens when you use the "global" command. This simplifies it:

function foo()
{
    $x = 1; // $x is local to foo() with a value of 1
    global $x; // $x is now the global (undeclared) variable
    echo $x; // Echos null
}

That is what happened in your first example. You set a variable and then switched that variable name to an undeclared global variable. Simple solution:

function foo()
{
    global $x; // $x is the global (undeclared) variable
    $x = 1; // $x (the global) now has a value of 1
    echo $x; // Echos 1
}
foo(); // Runs foo an echos 1.
echo $x; // Also echos 1 because global $x is 1.

The question of is it proper to declare globals inside a function is a different matter all together. This is simply to answer your question of the "strange" behavior. Personally, I register globals in the $GLOBALS array and use that as necessary.

kainaw
  • 4,256
  • 1
  • 18
  • 38
  • Having grown up on BASIC, C and VB6 environment, I am used to global variables being GLOBAL. =) Java and C# prefer to create static objects that maintain global values. PHP allows for a mix of all this, which can become very confusing and frustrating, when accidentally stumbled across as code is migrated from a function based environment to an object based, to a namespaced object environment - where files are included by both the class auto loader and include statements. The conclusion of this exercise is ... use the Java and C# methods of encapsulating global values. – E Net Arch Jan 01 '15 at 01:38
  • I prefer to state it this way: There are many languages that are designed to protect you from yourself. PHP is not one of them. It is designed to push through nearly any (non-syntax) mistake you make and keep doing something - maybe not what you want, but something. – kainaw Jan 01 '15 at 12:54