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

38,062

Solution 1

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.

Solution 2

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.

Solution 3

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.

Solution 4

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.

Solution 5

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).

Share:
38,062
KRTac
Author by

KRTac

Updated on July 08, 2022

Comments

  • KRTac
    KRTac almost 2 years
    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?

  • Pradeep Kumar
    Pradeep Kumar over 14 years
    It should be noted that PHP 5.3 does address some of this with lambda functions allowing you to avoid using function declared in global scope for callbacks. +1 for maintainable, readable code advice
  • KRTac
    KRTac over 14 years
    Jeah, I always prefix variables that I intend to use globally with a underscore.
  • grossvogel
    grossvogel almost 14 years
    Can you not use a callback of the form array ($obj, 'callbackMethod') in calls to preg_replace_callback()? (I know, I've fallen prey to this OOP pitfall...)
  • Aditya M P
    Aditya M P over 12 years
    @KRTac but $_testVariable is usually understood to be a private variable - that's an informal standard to define private variables, not global ones.
  • eddiemoya
    eddiemoya over 11 years
    The question was not "should global variables ever be used?". The answer to that would be, 'sure on occasion if necessary'. The question is are they bad practice. The answer is 'yes, sometimes'. For the posters tiny project, nothing bad may come of it - however for larger projects with many team members and lots of moving parts, heavy use of global variables will make the code difficult to debug, nearly impossible to refactor, and a pain to even read. Can you use them sometimes,.. sure - do they kina suck,.. yeah!
  • samayo
    samayo over 10 years
    But the error mostly shows in which file/line the script is breaking so.. I don't see the problem here
  • pixeline
    pixeline about 9 years
    A common practice is to define global vars using ALL CAPS. example: $DB = 'foo';
  • HonoredMule
    HonoredMule almost 9 years
    Place where script broke != place where mistake was made.
  • Admin
    Admin over 8 years
    @eddiemoya Well said Eddie. There are so many people justifying bad practices like using global variables. You should avoid them like the plague. Any decent software engineering degree will drill this into you... the lecturers aren't just telling you for the hell of it... they know from decades of experience. You should use member functions where possible to access values that you need, for example get_query_var() in Wordpress etc.
  • Scoots
    Scoots over 6 years
    An alternative to having to pass $bob everywhere, is to make class Bar a singleton, storing an instance of Bar statically within Bar itself, and using a static method to instantiate / fetch the object. Then you can just $bob = Bar::instance(); whenever you need it.
  • Machavity
    Machavity over 6 years
    Just be aware that Singletons are considered an anti-pattern. Dependency Injection avoids those pitfalls
  • Scoots
    Scoots over 6 years
    There is some degree of contention within that post you linked to (For example, the top rated comment to the accepted answer and the second most upvoted answer both strongly disagree with the accepted answer), making me inclined to argue that the use of Singletons should be considered on a case-by-case basis, rather than summarily dismissed out of hand.
  • Frankenmint
    Frankenmint over 2 years
    thank you and I appreciate this practical wisdom here. As someone who didn't have much support from older folks or had to come in and 'prove myself' as the newbie, I wouldn't have said those things you say but at the end of the day. I think its a great tool to use if that's what you need to use, but it shouldn't be relied upon as your MAIN tool, as you're alluding to (learn and expand how to solve problems, its' a wonderful journey).
  • Prid
    Prid almost 2 years
    👏👏 you nailed it with the different perspectives. We need to "fail" in order to learn, and see why a "bad practice" is considered bad in order to understand it.