Understanding PHP Globals and Variable Scope in WordPress

One of the most maligned features of WordPress is the rampant use of “PHP global variables.” There are huge decades-long discussions in software development circles about why heavy reliance on globally scoped variables is a bad design decision, but that debate is beyond the scope of what I want to cover here. (If that topic is interesting to you, the C2 Wiki article on it is a good starting point for understanding the arguments.) What I want to explain is instead what variable scope means, and why and how global variables are used in WordPress.

As to the conflict, I’ll just say that there are lots or reasons that the programming and PHP community as a whole has moved away from global variables but there are a large number of reasons that the WordPress project and community have not. More important than that discussion is understanding its meaning and implications, so let’s get started.

One quick thing before we do. If you’re looking to learn WordPress development, we’ve written the best guide to it out there:

The Best Way to Learn WordPress Development

Get Up and Running Today!

Up and Running is our complete “learn WordPress development” course. Now in its updated and expanded Third Edition for 2018, it’s helped hundreds of happy buyers learn WordPress development the fast, smart, and thorough way.

Here’s what they have to say:

“I think anyone interested in learning WordPress development NEEDS this course. Watching the videos was like a bunch of lights being turned on.” -Jason, WordPress developer

“Other courses I’ve tried nearly always lack clear explanations for why WordPress does things a certain way, or how things work together. Up and Running does all of this, and everything is explained clearly and in easy-to-understand language.” -Caroline, WordPress freelancer

You Keep Using that Word… What is “scope”?

What this means is that any given unit of PHP will either have access to variables in the global scope, or only have access to the variables declared inside the currently executing function.

Scope is a popular brand of mouthwash in the United States. But it’s also, and more importantly, about what’s relevant and visible to who and where. Programmers use the phrase “out of scope” when talking about activities or ideas that aren’t currently relevant to what they’re working on, and that’s got a lot to do with variable scope.

Basically, languages are written such that variables are accessible only within in a certain context, or scope. This is done it various ways, and based on various rules in different languages, but its purpose is to prevent the problem that one part of a program may set $i to 5, and while it’s waiting to use that value, and another part sets it to 981235792 or “cucumber.” If they’re both using the same $i, one of those parts of the program is highly likely to malfunction. Variables are given scope to prevent programs (and programmers’ heads) from exploding. The specific rules that control what variables are accessible in which places vary from programming language to programming language. What’s relevant to someone interested in WordPress and PHP is the specific way it works in that context.

PHP as a language uses function scoping. What this means is that any given unit of PHP will either have access to variables in the global scope, or only have access to the variables declared inside the currently executing function. There are some specific complications to this explanation that we’re going to skip for this article, but that’s essentially the story.

Playing with Scope in PHP

In this section I just want to run you through what all this scope stuff looks like in some basic PHP.

$global = "I am a global variable because I wasn't defined inside a function.";

my_global_function();
my_nonglobal_function($global);
function my_global_function() { 
     global $global; 
     echo $global;
}

function my_nonglobal_function($global) {
     echo $global;
}

As we said in the last section, there are really only two relevant scopes in PHP for variables you create, global and function. (There is a third type of scope, but if you want to know more about superglobals like $_GET, but they’re too big of a topic to tackle here.) Because we’re declaring the variable $global outside of a function, it will automatically have global state.

A variable that’s inside of a function can be accessed in two ways. First, it can be accessed in PHP by using the global keyword. This is what our first called function, my_global_function, does. By asserting that it wants the global variable $global, the echo — which is just PHP vocabulary for “throw onto the screen” — can output the string that we declared in the first line of the example. If we’d skipped the global line, we’d — depending on settings — either see a PHP error, or nothing on the screen at all. Neither is what we wanted.

The other way that we can use the pre-declared variable $global is that we can pass it into the function as a parameter. This allows us to be a little more certain about what variable we’re truly getting in the function, because it’s a hand-off, and it allows us to to skip straight to the echo $global without a stop off to “import” the variable.

As you can see, these are two functions that both accomplish the same thing. You’ll see both methods occur in various places in various PHP projects. Use of global has fallen out of favor in the PHP community because of the risk that before our function got around to access $global it could easily have been changed to anything and we’d be left having made a wrong assumption about it and quite possibly causing errors. The method of passing the relevant variables into the function when it is called is thus preferred in most modern projects that don’t worry about backwards-compatibility as much as WordPress.

Scope in WordPress

As I said at the top, WordPress relies heavily on global variables. (Here’s the list of all its globals.) As such, it is exceptionally common that you’ll see a function start with a line like:

global $post

Hopefully by now you’ve got a pretty good idea of what this is doing: importing in the entire global $post variable — which template tag functions like the_title() (or ones you make yourself) rely on — to local scope so it can act on it. This is so common you’ll see people forgot the need to declare the global or add the line at the top of their function when it’s not really necessarily. (It’s usually unnecessary because the programmer never accesses anything on $post directly after they “import” it from the global scope.)

Another prime example, other than inside the loop with template tags like the_ID() and the_content() of where global scope is used within WordPress is the mythical Loop itself. If you’ve written a custom WP_Query you may have suspected it, but the way you can use object-less methods like have_posts() and the the_post() inside of your template hierarchy files is that under the hood you’re calling those same methods on a global instance of WP_Query that WordPress has set up for you. (I like to tell beginners to just think of this as a “magic bag of posts,” but under the hood experts understand that it’s just a WP_Query object.)

What We’ve Learned: PHP global variables

Where you can avoid it, it’s generally considered a better idea to not add things to the PHP global scope. Given a choice between passing in a variable to the new function using it as a parameter, or adding your variable to the global scope, its best practice to do the former. But because WordPress is so conservative, global variables aren’t likely to leave us anytime soon. For that reason, you’ve earned a valuable power by understanding them. Happy hacking!


3 Responses

Pingbacks