52

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.

Spudley
  • 166,037
  • 39
  • 233
  • 307
Francisc
  • 77,430
  • 63
  • 180
  • 276

4 Answers4

83

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

Akash lal
  • 314
  • 6
  • 18
Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • 2
    I agree with you, $GLOBALS is far better than "global" – Stef Apr 03 '12 at 13:18
  • 18
    +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?). – Mark Jun 28 '12 at 16:13
  • @Artefacto, Regarding point 2 on readability (and on Sara Golemon), it just means your IDE is lousy. – Pacerier Aug 11 '13 at 17:53
  • @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. – Pacerier Aug 13 '13 at 13:51
  • @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. – Artefacto Aug 13 '13 at 14:20
  • @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 Aug 13 '13 at 15:23
  • .....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. – Pacerier Aug 13 '13 at 15:24
  • @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). – Artefacto Aug 13 '13 at 16:26
  • @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. – Pacerier Aug 13 '13 at 16:34
  • 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 :) – jave.web Dec 01 '13 at 21:02
32

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
reko_t
  • 55,302
  • 10
  • 87
  • 77
  • 3
    @Francisc If you really want to, you can pass it by reference. – Artefacto Aug 26 '10 at 10:14
  • 1
    I attached an example to demonstrate using a reference like Artefacto suggested. – reko_t Aug 26 '10 at 10:20
  • 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? – Francisc Aug 26 '10 at 10:54
  • 3
    `function writeFunction(&$output, $str) { $output .= $str; }` and to use it: `writeFunction($output, "something");` – reko_t Aug 26 '10 at 10:55
  • Ok, so you would say that is much better than using globals $output, correct? – Francisc Aug 26 '10 at 11:26
  • 2
    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. – reko_t Aug 26 '10 at 11:33
  • 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``) – JasonWoof Jul 11 '13 at 07:55
  • @JasonWoof - How is his code unreadable? This is the standard way to do things. – Craige Jul 12 '13 at 15:33
  • @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. – JasonWoof Jul 15 '13 at 08:29
  • @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 Jul 15 '13 at 13:20
  • ...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) – Craige Jul 15 '13 at 13:22
  • @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. – JasonWoof Aug 22 '13 at 21:28
  • 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 Dec 01 '13 at 21:01
  • @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 Sep 20 '15 at 14:01
  • @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. – BlackPanther Sep 20 '15 at 14:04
  • 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 Sep 22 '15 at 04:04
  • 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 Sep 22 '15 at 04:12
  • 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. – reko_t Sep 22 '15 at 04:29
4

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

Pikamander2
  • 7,332
  • 3
  • 48
  • 69
Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
  • 2
    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 Aug 26 '10 at 10:21
0

global $var; is equivalent to $var =& $GLOBALS['var'].

Some people suggested that it is faster than using $GLOBALS, however it's not necessarily the case. If you use the variable only once, $GLOBALS will be faster, because you won't waste time for assignment.

However, if you do use the variable multiple times, using global (or the equivalent assignment) is faster, because search the array for the var key only once.

That's it about speed. However, the speed difference is really small, and readability is more important. However, different people have different preferences about readability -- I prefer global, some other people answering here prefer $GLOBALS, so it's up to you to decide what looks better.

Mewp
  • 4,715
  • 1
  • 21
  • 24
  • 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. – Artefacto Aug 26 '10 at 10:41
  • @Artefacto: Hm, I thought that they were really equivalent. Thanks for pointing that out, I'll try to find more information about this. – Mewp Aug 26 '10 at 10:44
  • 1
    As to well, the second is wrong, run "Profile code" on this http://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. – Artefacto Aug 26 '10 at 10:48
  • @Artefacto: I see now. Also, http://codepad.viper-7.com/YfjsII shows that the assignment indeed uses one more opcode than global. – Mewp Aug 26 '10 at 11:00