Are global variables in PHP considered bad practice? If so, why?

function foo () {
global $var;
// rest of code
}

In my small PHP projects I usually go the procedural way. I generally have a variable that contains the system configuration, and when I nead to access this variable in a function, I do global $var;.

Is this bad practice?

40032 次浏览

When people talk about global variables in other languages it means something different to what it does in PHP. That's because variables aren't really global in PHP. The scope of a typical PHP program is one HTTP request. Session variables actually have a wider scope than PHP "global" variables because they typically encompass many HTTP requests.

Often (always?) you can call member functions in methods like preg_replace_callback() like this:

preg_replace_callback('!pattern!', array($obj, 'method'), $str);

See callbacks for more.

The point is that objects have been bolted onto PHP and in some ways lead to some awkwardness.

Don't concern yourself overly with applying standards or constructs from different languages to PHP. Another common pitfall is trying to turn PHP into a pure OOP language by sticking object models on top of everything.

Like anything else, use "global" variables, procedural code, a particular framework and OOP because it makes sense, solves a problem, reduces the amount of code you need to write or makes it more maintainable and easier to understand, not because you think you should.

I agree with the accepted answer. I would add two things:

  1. Use a prefix so you can immediately identify it as global (e.g. $g_)

  2. Declare them in one spot, don't go sprinkling them all around the code.

Global variables if not used carefully can make problems harder to find. Let's say you request a php script and you get a warning saying you're trying to access an index of an array that does not exist in some function.

If the array you're trying to access is local to the function, you check the function to see if you have made a mistake there. It might be a problem with an input to the function so you check the places where the function is called.

But if that array is global, you need to check all the places where you use that global variable, and not only that, you have to figure out in what order those references to the global variable are accessed.

If you have a global variable in a piece of code it makes it difficult to isolate the functionality of that code. Why would you want to isolate functionality? So you can test it and reuse it elsewhere. If you have some code you don't need to test and won't need to reuse then using global variables is fine.

Who can argue against experience, college degrees, and software engineering? Not me. I would only say that in developing object-oriented single page PHP applications, I have more fun when I know I can build the entire thing from scratch without worrying about namespace collisions. Building from scratch is something many people do not do anymore. They have a job, a deadline, a bonus, or a reputation to care about. These types tend to use so much pre-built code with high stakes, that they cannot risk using global variables at all.

It may be bad to use global variables, even if they are only used in the global area of a program, but let's not forget about those who just want to have fun and make something work.

If that means using a few variables (< 10) in the global namespace, that only get used in the global area of a program, so be it. Yes, yes, MVC, dependency injection, external code, blah, blah, blah, blah. But, if you have contained 99.99% of your code into namespaces and classes, and external code is sandboxed, the world will not end (I repeat, the world will not end) if you use a global variable.

Generally, I would not say using global variables is bad practice. I would say that using global variables (flags and such) outside of the global area of a program is asking for trouble and (in the long run) ill-advised because you can lose track of their states rather easily. Also, I would say that the more you learn, the less reliant you will be on global variables because you will have experienced the "joy" of tracking down bugs associated with their use. This alone will incentivize you to find another way to solve the same problem. Coincidentally, this tends to push PHP people in the direction of learning how to use namespaces and classes (static members, etc ...).

The field of computer science is vast. If we scare everyone away from doing something because we label it bad, then they lose out on the fun of truly understanding the reasoning behind the label.

Use global variables if you must, but then see if you can solve the problem without them. Collisions, testing, and debugging mean more when you understand intimately the true nature of the problem, not just a description of the problem.

Reposted from the ended SO Documentation Beta

We can illustrate this problem with the following pseudo-code

function foo() {
global $bob;
$bob->doSomething();
}

Your first question here is an obvious one

Where did $bob come from?

Are you confused? Good. You've just learned why globals are confusing and considered a bad practice. If this were a real program, your next bit of fun is to go track down all instances of $bob and hope you find the right one (this gets worse if $bob is used everywhere). Worse, if someone else goes and defines $bob (or you forgot and reused that variable) your code can break (in the above code example, having the wrong object, or no object at all, would cause a fatal error). Since virtually all PHP programs make use of code like include('file.php'); your job maintaining code like this becomes exponentially harder the more files you add.

How do we avoid Globals?

The best way to avoid globals is a philosophy called Dependency Injection. This is where we pass the tools we need into the function or class.

function foo(\Bar $bob) {
$bob->doSomething();
}

This is much easier to understand and maintain. There's no guessing where $bob was set up because the caller is responsible for knowing that (it's passing us what we need to know). Better still, we can use type declarations to restrict what's being passed. So we know that $bob is either an instance of the Bar class, or an instance of a child of Bar, meaning we know we can use the methods of that class. Combined with a standard autoloader (available since PHP 5.3), we can now go track down where Bar is defined. PHP 7.0 or later includes expanded type declarations, where you can also use scalar types (like int or string).

As:

global $my_global;
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']

is bad practice (Like Wordpress $pagenow)... hmmm

Concider this:

$my-global = 'Transport me between functions';

is PHP error But:

$GLOBALS['my-global'] = 'Transport me between functions';

is NOT error, hypens will not clash with "common" user declared variables, like $pagenow. And Using UPPERCASE indicates a superglobal in use, easy to spot in code, or track with find in files

I use hyphens, if Im lazy to build classes of everything for a single solution, like:

$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';

But In cases of a more wider use, I use ONE globals as array:

$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';

The latter is for me, good practice on "cola light" objectives or use, instead of clutter with singleton classes each time to "cache" some data. Please make a comment if Im wrong or missing something stupid here...