PHP global or $GLOBALS

46,105

Solution 1

What you should really do is pass the variable to the function instead of using a global at all.

An example how to change a variable outside of the function via passing it as reference parameter:

function myFunc(&$myVar)
{
    $myVar = 10;
}

$foo = 0;
myFunc($foo);
var_dump($foo); // yields 10

Solution 2

Well, you should only use globals in limited circumstances, but to answer your question:

  1. global is potentially marginally faster (it will rarely make a difference).
  2. $GLOBALS (not $GLOBAL) is more readable, because every time you see it, you know you are accessing/changing a global variable. This can be crucial in avoiding nasty bugs.
  3. Inside the function, if you want to unset a global variable, you must use unset($GLOBALS['varname']), not global $varname; unset($varname);.

As to points 1 and 2, I'll quote Sara Golemon here:

What does that mean for your use of the $GLOBALS array? That's right, the global keyword is technically faster. Now, I want to be really clear about one thing here. The minor speed affordance given by using your globals as localized [compiled variables] needs to be seriously weighed against the maintainability of looking at your code in five years and knowing that $foo came from the global scope. something_using($GLOBALS['foo']); will ALWAYS be clearer to you down the line than global $foo; /* buncha code */ something_using($foo); Don't be penny-wise and pound foolish..

Solution 3

Use global at the top of your function. That way, you can easily see what globals are used.

Share:
46,105
Francisc
Author by

Francisc

Updated on January 31, 2020

Comments

  • Francisc
    Francisc over 4 years

    Is there a best practice / recommendation when I want to use a variable declared outside of a function when it comes to using:

    1. global $myVar
    2. $GLOBALS['myVar']

    Thank you.

  • Artefacto
    Artefacto over 13 years
    @Francisc If you really want to, you can pass it by reference.
  • reko_t
    reko_t over 13 years
    I attached an example to demonstrate using a reference like Artefacto suggested.
  • Artefacto
    Artefacto over 13 years
    Except when the function is long (e.g. a big switch statement), and now you don't know what's a global and what's not. You can declare which globals you use with a phpdoc (@global).
  • Artefacto
    Artefacto over 13 years
    Your first two paragraphs are wrong. Well, the first is half-wrong. It's semantically equivalent, but they don't translate to the same opcodes and global $var is faster than $var =& $GLOBALS['var']. The second paragraph is just plain wrong.
  • Mewp
    Mewp over 13 years
    @Artefacto: Hm, I thought that they were really equivalent. Thanks for pointing that out, I'll try to find more information about this.
  • Artefacto
    Artefacto over 13 years
    As to well, the second is wrong, run "Profile code" on this codepad.viper-7.com/roRI8g You'll see that global is just one hash lookup plus storage in a compiled variable. The $GLOBALS variant entails two hash lookups. It's not stored in any variable, but it doesn't make any difference versus storing in a compiled variable, performance wise.
  • Francisc
    Francisc over 13 years
    What I want to do is have an $output variable that gets concatenated with new data contantly and instead of $output.='something' I want to do writeFunction('something'). The function itself would be function writeFunction($str){global $output;$output.=$str;) Is there a better way of doing that?
  • reko_t
    reko_t over 13 years
    function writeFunction(&$output, $str) { $output .= $str; } and to use it: writeFunction($output, "something");
  • Mewp
    Mewp over 13 years
    @Artefacto: I see now. Also, codepad.viper-7.com/YfjsII shows that the assignment indeed uses one more opcode than global.
  • Francisc
    Francisc over 13 years
    Ok, so you would say that is much better than using globals $output, correct?
  • reko_t
    reko_t over 13 years
    Yes. Functions written in this way are not limited to only dealing with global variables. You can also use them on variables declared on local scopes. Nor are they limited to using a variable from outside with specific name.
  • Stef
    Stef about 12 years
    I agree with you, $GLOBALS is far better than "global"
  • Mark
    Mark almost 12 years
    +1 for actually answering the question that was asked. Globals might not be best practices but sometimes we have to work with them (WordPress, anyone?).
  • JasonWoof
    JasonWoof almost 11 years
    This does not say which of the methods asked about are better, and you're suggesting something with very unreadable code. (even worse than global $myVar)
  • Craige
    Craige almost 11 years
    @JasonWoof - How is his code unreadable? This is the standard way to do things.
  • JasonWoof
    JasonWoof almost 11 years
    @Craige It's bad for readability because most readers (unless they happened to start reading far enough back to see the global directive) will assume that $myVar = 3 will only effect the local scope.
  • Craige
    Craige almost 11 years
    @JasonWoof - This answer is suggesting NOT using the global directive. I think you mean the function definition. In either case, in well written code, methods should be short, clear and concise. Sometimes, you just need to modify external values. The key is to make it clear that you are doing that. Passing by reference is the standard way to achieve this.It is more concise than using globals because you know exactly where that value is coming from; it is being passed in by the code that called the method. If you were to use a global, you have no concrete idea as to where that value...
  • Craige
    Craige almost 11 years
    ...came from, whether or not it is set, or what other code may be relying on this magic global variable. Globals are hell, and should be avoided for saner coding practices whenever possible (Which is 98% of the time)
  • Pacerier
    Pacerier over 10 years
    @Artefacto, Regarding point 2 on readability (and on Sara Golemon), it just means your IDE is lousy.
  • Pacerier
    Pacerier over 10 years
    @Artefacto, Most of code creation and modification is done on an editor. I think optimizing for black-and-white view should have lowest priority, and if any, they are easily offset by small advantages other options offer in color view. Even online code displays have colors.
  • Artefacto
    Artefacto over 10 years
    @Pacerier 1) online code displays don't parse global to detect which variables are local, 2) not everyone uses an IDE (I remembers reading more half the people on Facebook didn't and used something like vim instead and at least my syntax highlighting for PHP files in vim does not detect the variable scope) and 3) even if your IDE detects globals, $GLOBALS will be clearer than whatever color you choose, even if it's green over pink.
  • Pacerier
    Pacerier over 10 years
    @Artefacto, 1) That's what I'm saying. It just means the code display needs to buck up. 2) Same as above. And pardon me for using the term IDE, because what I actually meant was "development environment", whether it is considered integrated or not. 3) Simply not true. If we use global $myVar, the DE can detect instances of that global variable and assign it a color. Once we see.....
  • Pacerier
    Pacerier over 10 years
    .....that color, we know that variable is global-ed. If we use $GLOBALS when we want global, the DE cannot differentiate between the time when we explicitly want $GLOBALS and the time when we want global. It needs to give all $GLOBALS['myVar'] the same color.
  • Artefacto
    Artefacto over 10 years
    @Pacerier OK, you don't think the fact that online code display or the standard vim syntax plugins don't detect globals is important. And we disagree on what's clearer. Fine, let's disagree. But note that not even the best IDE can detect all instances of globals (think variable variables or otherwise dynamic variables). Consider also a file's top scope. An IDE also doesn't know whether variables that show up there are globals or local variables (think templates included from a function).
  • Pacerier
    Pacerier over 10 years
    @Artefacto, correct but there's a difference between doing what it can do, vs not even doing what it can do. Also, it's not that I think those points weren't important, but I'm saying it's a DE problem and it just means the DE needs to buck up. Your answer has 3 points, the first and last are cool hard raw facts. Point 2 is subjective and subject to change when the environment changes.
  • JasonWoof
    JasonWoof over 10 years
    @Craige oops, yes, I said "see the global directive" and in this case it was just the & sign... which is even easier to miss. In my book, passing an integer by reference is unusual, and violating norms like this often lead to hard-to-find bugs. My beef with passing things by reference is similar to my beef with the global directive: when you look at the code that modifies the value (without reading back to where that variable came from) it looks like code that's modifying a local variable. Code that looks like it's doing something other than what it's actually doing is hard to debug.
  • jave.web
    jave.web over 10 years
    I did a little localhost-benchmarking on global & $_GLOBALS , what is faster actually vary, but overall winner was the $_GLOBALS array - after about 600 000 entries the total time count of $_GLOBALS was about 13seconds less than global keyword - BUT it was running 1000cycles and microtime after minus microtime before - so it could be just for this case :) anyway $_GLOBALS array seems more readable to me :)
  • jave.web
    jave.web over 10 years
    ad 1) I did a little localhost-benchmarking on global & $_GLOBALS , what is faster actually vary, but overall winner was the $_GLOBALS array - after about 600 000 entries the total time count of $_GLOBALS was about 13seconds less than global keyword - BUT it was running 1000cycles and microtime after minus microtime before - so it could be just for this case :) anyway $_GLOBALS array seems more readable to me :)
  • BlackPanther
    BlackPanther over 8 years
    @reko_t Can I ask what is the problem with using globals? Is it declaring a global variable? or accessing it? If its declaring, then clearly this answer is not an alternative, but if it is about accessing the global variable, then even though using a longer method, you are still accessing it. So why this method?
  • BlackPanther
    BlackPanther over 8 years
    @reko_t If its about semantics, I am using a global variable to act as an error buffer, so I could flush it out at the end of the page and display all error messages for the user at the end of the page. In that case, is passing a Global Error Buffer as an argument to all the functions I write be good semantic? That doesn't make sense either. I really would like to know why this method is better, so that I could use it as a standard for my programs.
  • reko_t
    reko_t over 8 years
    Look into exceptions. You should bootstrap your application so that it runs through a single point of entry always, and you have a try/catch there, if some part of your application throws an exception that is not handled, then you catch it there, and then display an error to the user.
  • reko_t
    reko_t over 8 years
    I understand your point though, sometimes there are objects that are used everywhere and you don't really want to pass that to every function ever. One approach to solving that issue is to use Dependency Injection. DI also makes testing code much easier, since you can easily mock the injected services for tests, etc.
  • reko_t
    reko_t over 8 years
    Globals can be considered 'bad' for various reasons. They implicitly couple some data/functionality, and it can easily become a maintenance hell when you have no idea where all that data comes from, where is it used, etc. Imagine that suddenly you got some large project that you didn't code but now you have to maintain it, and it's full of global variables. It really hearts the readability of your code. It also makes testing a pain, as the state is unpredictable and it's difficult to "clean the slate" between tests.