For all of you who landed on this post looking for a way to give your PHP function full variable scope, please bear with me and my long introductions, or just skip right to the answer.
I’ve been programming for over 15 years, and like most coders with that much experience, I started out in BASIC. QBasic to be precise. I’ve been most active in QBasic, Visual Basic, and Blitz Basic/Blitz3D/BlitzMax. In fact, most of my programming experience has been in languages that derived from BASIC. The problem with programmers like me is that we never really grow out of the methodologies and concepts that these languages promote, even though most of them are considered bad practice these days.
For the past 6 years or so, I’ve been programming almost exclusively in PHP, a language that has offered a complete framework for object oriented programming since version 5. Although I like the principles of MVC and can build and work with OOP projects, it’s not really for me. I do things my way, and that’s procedurally.
One thing that’s always bugged me about modern languages is that good old gosub routines have been deprecated. You can no longer call a block of code unless that code is in a function, and functions don’t have full variable scope. I.e. if you have to explicitly declare each and every variable that you want your function to have global access to. To me, this goes against the point of OOP, which is to promote coding techniques that reduce the need to rewrite the same code over and over again.
To get to the point, (eventually), I was working on a project of mine the other day that I’ve been writing procedurally, and I decided to rework the way the main framework routed the instructions. I needed a chunk of re-usable code that had full variable scope, and I wasn’t prepared to go back through the entire framework changing the way variables were constructed so that I could easily pass a group of them to this function. The time had come to figure out how to cheat this system, and that’s exactly what I did!
Procedural coders take note – THIS is how we create a function, in PHP, that has full variable scope!
1. Right at the very start of your code, use the get_defined_vars() function to grab an array of everything that’s already been defined. I’ll explain why later. If your application uses sessions, you’ll want to session_start() first to ensure that this function returns your session variables too.
session_start();
$presetGlobals = get_defined_vars();
2. Next, whenever you make a call to your function, again grab an array of every variable currently defined and pass it along with the call.
my_function(get_defined_vars());
3. Now, it’s important to note that although functions in PHP don’t have access to variables defined outside of them, certain variable names are reserved such as $_SERVER and $_SESSION. Your function can already access these so we need to strip them from the array that’s just been passed to it. This is why we created $presetGlobals above, before running any other code. So here we loop through everything in that list and remove it from the array we’ve just grabbed, leaving us with only the variables we don’t already have global access to. Remember you need to make the global call to this original array otherwise it’s outside of the scope
function my_function($theGlobals) {
global $presetGlobals;
foreach($presetGlobals AS $key => $val) {
unset($theGlobals[$key]);
}
}
4. Oh, and we also want to remove $presetGlobals from this array too, otherwise we have a somewhat recursive nest.
function my_function($theGlobals) {
global $presetGlobals;
unset($theGlobals['presetGlobals']);
foreach($presetGlobals AS $key => $val) {
unset($theGlobals[$key]);
}
}
5. Finally, $theGlobals contains an array of all the variables we need access to. Here we have two choices – either define each variable again, with the same content, or make a global call to each variable. The difference is that if we define them all again, (code example 1 below), any changes made to them will be lost once the function exits. However if we make a global call to them, (code example 2 below), it’s the original variable that we’re working with so changes are kept.
Example 1:
function my_function($theGlobals) {
global $presetGlobals;
unset($theGlobals['presetGlobals']);
foreach($presetGlobals AS $key => $val) {
unset($theGlobals[$key]);
}
foreach($theGlobals AS $key => $val) {
$$key = $val;
}
}
Example 2:
function my_function($theGlobals) {
global $presetGlobals;
unset($theGlobals['presetGlobals']);
foreach($presetGlobals AS $key => $val) {
unset($theGlobals[$key]);
}
foreach($theGlobals AS $key => $val) {
global $$key;
}
}
I should note that this is considered to be very bad programming practice and if you’re following the rules, a better approach would be to declare all your globally used variables within an array so that you just need to call for that one array in your functions, but I’m sure I’m not the only programmer out there that’s been looking for the above, so I really wanted to share this little hack.