Global variables

PHP was originally a purely procedural programming language to which object-oriented language features were subsequently added. Looking back, it can be said that it took quite a while before it was possible to program "properly" object-oriented with PHP. This is the reason why widely used PHP software such as Drupal or Wordpress look object-oriented at first glance, but behind the scenes are still very much rooted in their procedural past.

Object orientation in PHP is at least on a par with other programming languages.

First of all, we should refrain from using global variables. Let's take a look at an example:

<?php declare(strict_types=1);

$a = 'test';
some_function($a);
var_dump($a);

function some_function($a): void
{
    var_dump($a);
}
globalAndLocalVariable.php

How many variables $a are there here? That's right, there are two. First, there is the global variable $a above and within the function there is the parameter and thus a local variable, which is also called $a. This is called shadowing, by the way.

This program outputs test twice because the two variables $a have the same value - by chance, so to speak:

globalAndLocalVariable.php:9:
string(4) "test"
globalAndLocalVariable.php:5:
string(4) "test"
Output of globalAndLocalVariable.php
Execute globalAndLocalVariable.php

We could also rename the second $a, for example to $b:

<?php declare(strict_types=1);

$a = 'test';
some_function($a);
var_dump($a);

function some_function($b): void
{
    var_dump($b);
}
globalAndRenamedLocalVariable.php

Unsurprisingly, this works in exactly the same way:

globalAndLocalVariable.php:9:
string(4) "test"
globalAndLocalVariable.php:5:
string(4) "test"
Output of globalAndLocalVariable.php
Execute globalAndLocalVariable.php

To make a point, however, we stick with the original duplication of names, i.e. $a twice. We can change a local variable at any time, as it "belongs" to us exclusively:

<?php declare(strict_types=1);

$a = 'test';
some_function($a);
var_dump($a);

function some_function($a): void
{
    $a .= '!';

    var_dump($a);
}
globalAndModifiedLocalVariable.php

If we change the value of $a within the function, this has no effect on the global variable $a:

globalAndModifiedLocalVariable.php:11:
string(5) "test!"
globalAndModifiedLocalVariable.php:5:
string(4) "test"
Output of globalAndModifiedLocalVariable.php
Execute globalAndModifiedLocalVariable.php

We see test! first, because the function call some_function() is executed before the global var_dump(). Now let's make some real nonsense and tell PHP that we want to access the global variable $a within the function some_function():

<?php declare(strict_types=1);

$a = 'test';
some_function($a);
var_dump($a);

function some_function($a): void
{
    global $a;

    var_dump($a);
}
globalVariable.php

Of course, we shouldn't do this because it causes confusion. Nevertheless, the result remains unchanged for the time being, because both the global and the local $a have the same value anyway:

<?php declare(strict_types=1);

$a = 'test';
some_function($a);
var_dump($a);

function some_function($a): void
{
    global $a;

    var_dump($a);
}
globalVariable.php

But what happens if we now change $a within the function?

<?php declare(strict_types=1);

$a = 'test';
some_function($a);
var_dump($a);

function some_function($a): void
{
    global $a;

    $a .= '!';

    var_dump($a);
}
modifiedGlobalVariable.php

Let's take a look:

modifiedGlobalVariable.php:13:
string(5) "test!"
modifiedGlobalVariable.php:5:
string(5) "test!"
Output of modifiedGlobalVariable.php
Execute modifiedGlobalVariable.php

Ouch. Now it's a bitter revenge that we're working with the global variable instead of a local variable in the function, because the seemingly local change now has global effects. If we do something like this in a sufficiently complex "real" application, then good night. Incidentally, this is referred to as a side effect, which is a mistranslation of the English term side effect, which actually means "side effect" in the sense of an undesirable side effect, as with a drug.

Our function has just destroyed the global system state.

Why we avoid global

This is exactly the problem with global variables. In a small example program, it may not look too bad to use global variables. In a real application, especially when several different developers are working on it, the use of global variables quickly becomes unmanageable. This is mainly due to the fact that anyone can access all global variables from anywhere and at any time, not only for reading but also for writing.

Before you use a global variable, come to Wolfratshausen on foot and ask me for permission.

Procedural programming in PHP has no really meaningful answers to the question of how to avoid global variables. There is no really good way to define data structures besides the array, if you use stdClass it's no better. So we would get longer and longer parameter lists if we always provided each function with all the data it needs. And the return values in particular are a problem if we don't want to either return arrays or work with references.

This is a good reason for programming in an object-oriented way, because then we can use objects both as parameters and as return values.

Even more globality

The problem of global variables and thus global system state becomes even worse if we save it permanently, because then we have persistent global system state.

In addition to global variables, PHP also knows so-called superglobal variables, which are automatically available in every scope even without an explicit global declaration.

Questions for learning control

  1. What are the advantages of explicitly declaring global variables within functions and methods?
  2. A colleague suggests writing functions without parameters and using global variables for passing and returning instead. What are the disadvantages of this?
  3. A basic problem with global variables is their mutability. Discuss whether you should therefore use global constants instead.