The Missing PHP Global |
Written by David Conrad | |||||||
Page 2 of 2
SolutionThe solution to the problem was discovered by checking what the "global" variable $baseURL actually stored, and it turned out to be nothing at all. With this information what was going on became very obvious. The module was being included in the application at the global level but within some function of the existing system. The programmer working on the existing system probably didn't even realize that the block of code that they were working on was actually being executed within a function - but it was. The actual code being executed was something like:
You can now see the problem for what it is. The $baseURL variable isn't being declared as global, but as local to an internal function. The GetData function is local to the majorAction function but the global declaration isn't relative. Global means top level global and hence the $baseURL variable is a true global variable and undefined. So what is the solution? If you are writing code that could possibly be used within another function - and this is perfectly OK in PHP - then you can't simply define a top level variable and expect it to be global when you code is used. The top level of your code might have global context or it might have local context. There is a way, however, to ensure that a variable that you define is always a global variable irrespective ot the current context. The $GLOBALS associative array has true global scope - a superglobal in PHP jargon - and it contains all of the global variables as name-value pairs. A superglobal can be accessed from any context without needing a global declaration. In most cases the $GLOBALS array is used to access global variables without the need for the global keyword. For example:
is the same as:
Less well known, but fairly obvious, is the fact that it can also be used to create a global variable from any context. For example, if the module is changed to:
then it will work perfectly well, even if it is included within a function and hence not in the global context. You can use the same technique to create a global variable from within a function. For example:
creates $myVariable as a global. PatternYou could start off this discussion of the pattern to point out that using a global variable in this way is an anti-pattern - i.e. something you shouldn't do. In practice, however, creating global variables is a very easy way to set up an execution environment and many programmers do it, even if it isn't a great idea. One reason why it isn't a great idea is that if you are writing some code to be used in another program how can be sure that you aren't using the same name as a global variable that already exists? In short, how can you avoid name collisions? You can also point out that you shouldn't include code within functions. You should always load libraries at the topmost level exactly so that any globals really are global. This is a good idea but it isn't something that is as easy to enforce as you might think. Many PHP programmers work on systems that define places where code to do a particular job is to be placed. The innocent programmer might well think that they are working at the top level when in fact they are actually being wrapped by a function that the system uses to call the code. Even if this is made clear, the programmer might choose not to pollute the system code by adding includes to the top level code. The only potential problem with placing includes within functions is that all the variables defined within the included file are defined as local to that function. If you are going to use a global variable then you really should define it at the top level of your program or wherever is convenient using the $GLOBALS super global array.
More Puzzles
|