PHP and Register Global Variables

From Lunarpages Web Hosting Wiki

What are Register Global Variables?

It is a frequent necessity to transfer variable values between pages. You may have an HTML form which asks for user input to named fields. These fields (as well as hidden variables) will be transferred to a PHP page for processing. This may be the same page that defines the form, or a different one. A method of either 'post' or 'get' must be given in the form tag.

Another way to transfer variable data to another page is make an HTML link (such as with [click this link).This of course can be entered on the browser's address line, too. This information (the stuff after the ?, or "var_name_1=data&var_name_2=data") is known as a URL Query String ("UQS") and can be treated like a "GET" form submission.

So, how do these variables and their data get into my PHP code?

Once upon a time, most PHP programmers simply grabbed variables and values by using them in their code. Let's say you had two fields in a form, named "user_name" and "user_email". You could simply use $user_name and $user_email in your code (the receiving, or target, page), and they would have the values filled in by the user in the form. Life was simple, wasn't it? $user_name and $user_email were examples of a special kind of PHP variable, called a register global variable. You simply used it, and it was magically there to pull in data transferred from a form or a link on another page.

So what's the problem, or why doesn't my code work anymore?

You've been happily using register global variables for years, and all of a sudden, your code doesn't work anymore. You might get PHP or MySQL errors, or a blank page, or your system just isn't working as expected. Maybe you added some debug print statements, and discovered that these register global variables are now simply undefined (have no value).

What happened? Well, the short story is that you just can't trust people on the Web like you used to. I won't go into the gory details, but when using register global variables, anyone can invoke your page from their own form or the browser address line with fake variable data. That is, they can define variables with values that shouldn't be. This is considered a serious security hole, especially if you fail to initialize your PHP variables and just assume a null initial value. Someone can "plant" a bogus starting value and you wouldn't realize it.

The PHP development community has decided that this is such a serious security problem that they are actively discouraging the use of register global variables. Up through PHP version 4.1, register global variables were enabled ("on") by default. Starting in PHP 4.2, installations are being encouraged to turn register global variables off by default, but Lunarpages began doing this only recently, long after PHP 5 was released, and is turning register global variables off during PHP upgrades. PHP 5 is the current production level of PHP (although Lunarpages still offers PHP 4 on many servers). PHP version 6 will be out in the near future (although Lunarpages will undoubtedly stay at version 5 until it's satisfied that PHP 6 is stable enough for production use). PHP 6 won't even permit you to use register global variables, so you'll need to fix your code by then.

So, at some point, Lunarpages upgraded PHP (or even, without an upgrade) on your server, and turned off register global variables. This means that these variables, when used in your code, no longer show up with the intended values, but are undefined (empty, in practical terms). This tends to break code that ran well for years, but is an unfortunate necessity in today's world, which is filled with hackers probing for weaknesses in your PHP scripts.

If your PHP code has been working fine for ages, and all of a sudden isn't (with or without explicit error messages), it's a pretty good bet that you're using register global variables and they've been turned off, breaking your code. It's easy enough (see the following section) to try turning "on" register global variables and seeing if that fixes the problem.

The Quick and Dirty way to keep using register global variables

If your Web site isn't going to exist much longer, or is due for a major rewrite soon anyway, or uses scripts that you don't feel like patching (e.g., osCommerce 2.2 MS2), you can still turn on register global variables (for the time being).

Note: this discussion assumes that you are on a shared server running Linux and Apache server (Basic and Business plans). If you are on a Virtual Private Server (VPS), dedicated server, or Windows-based server, these instructions may not apply, and you'll need to find out how to do it on your server. For example, on a Linux/Apache VPS or dedicated server, you may have your PHP settings in a file named httpd.conf instead. Maybe.

First, you need a file called php.ini that contains various settings for the use of PHP. You may already have one if you needed to, say, set larger limits for uploaded files. If not, you will have to create a new file named php.ini somewhere. It is simplest to put it in /home/YOUR_ACCOUNT_NAME/public_html/, but you should take measures to keep others from peeking into this file. Some people like to put it in /home/YOUR_ACCOUNT_NAME/ instead -- that's secure against prying eyes. It is possible to have just one php.ini that applies to your entire site, or you can have different php.ini files for the use of different subsystems. Of course, different php.ini files need to be placed in different directories, usually the "root" directory of the system that needs its particular settings.

The php.ini file, whether new or existing, and wherever it is, needs to contain the line:

register_globals = on

(Capitalization doesn't really matter.) The permissions are usually "644".

Second, you need to add lines to your .htaccess file to tell PHP where to find your applicable php.ini file. Let's say you put it in /home/YOUR_ACCOUNT_NAME/public_html/. The entry in .htaccess would be:

suPHP_ConfigPath  /home/YOUR_ACCOUNT_NAME/public_html

Obviously, YOUR_ACCOUNT_NAME in these instructions is replaced by your account name (the one you sign onto cPanel with). It's not the server name. You can have multiple .htaccess files in different directories to control your site, so make sure each one points to the appropriate php.ini file (a simple matter if you have only one). If you put your php.ini file in /home/YOUR_ACCOUNT_NAME/, that's all you need to do. However, if it was placed in any directory in or below /home/YOUR_ACCOUNT_NAME/public_html/, any browser will be able to look at it unless you add the following lines to the .htaccess file:

<Files php.ini>
order allow,deny
deny from all

That should keep out snoopers.

So, now you have a php.ini file controlling your PHP usage, with settings that include a request to turn register global variables back on so you can use them. Please note that in doing this, you are making your PHP code somewhat less secure than it would otherwise be. You also have an entry in the .htaccess file telling PHP where to find its php.ini file with the settings to use.

A final note: some old PHP books and instructions will tell you to put a line in .htaccess similar to:

php_value register_globals on

Don't do this. "php_value" doesn't work anymore on Lunarpages servers. Put PHP settings into your php.ini file.

The proper way to eliminate register global variables

While you can still turn register globals on using the instructions above, that is not a good long-term solution.

1) It keeps open a security hole that someone may be able to exploit, especially if you are using a canned script that hackers have the source to.

2) Eventually, Lunarpages will upgrade to PHP 6 and you won't even be able to turn register global variables on.

For PHP code that is going to be around for a while, you should upgrade it to no longer use register global variables. In a nutshell, you need to explicitly import POST or GET variables before using them. The easiest way is to have a section of code near the top of the receiving (target) page that defines your variables (the ones that are currently register global variables). In the example given earlier, where a form passes user_name and user_email to your page, if the form method is POST, you would write:

$user_name = $_POST['user_name'];
$user_email = $_POST['user_email'];

If the form method is GET, you would write:

$user_name = $_GET['user_name'];
$user_email = $_GET['user_email'];

There is a shortcut, so long as you are not using both GET and POST with the same named variables being passed (supposedly this is possible, but it sounds messy and ripe for problems to me). The $_REQUEST array is a combination (union) of $_GET and $_POST, so you can write instead:

$user_name = $_REQUEST['user_name'];
$user_email = $_REQUEST['user_email'];

and not have to worry about whether it was passed as GET or POST.

A few important notes

1) URL Query String variables can be imported using either $_GET or $_REQUEST. You cannot use $_POST with UQS variables.

2) With register global variables, if the variable was not defined in a form or UQS, it would not be set. Once you put in the above code (e.g., $user_name = $_REQUEST['user_name'];), [tt]$user_name[/tt] will be set (but empty) if that variable (user_name) wasn't passed in from the form! You will need to test $_REQUEST['user_name'] itself (with the isset() function), rather than testing the $user_name local variable.

3) You don't have to set a local variable to $_xxx['var_name'] -- you can simply use $_REQUEST['user_name'] in your code instead of $user_name. It's just that it's usually neater (and less typing) to load up a local variable ($user_name in this example) than to repeatedly type in the longer form. If you changing from using register global variables, you'll already have the $user_name throughout your code anyway -- why bother changing it?

4) Old timers in the PHP world have a habit of dropping the apostrophes around the associative array element name (e.g., $_REQUEST[user_name] instead of $_REQUEST['user_name']). This is a bad habit that has long been tolerated by PHP, but may not be for much longer. Get in the habit of making associative array element names as proper strings ('name' or "name").

By the way, osCommerce 2.2 RC1 and later no longer requires register global variables to be "on". Unfortunately, it may be a while before Fantastico upgrades beyond 2.2 MS2 (they may choose to wait until 2.2 final is released). You will need to manually install 2.2 RC2a or later to get rid of the need for register global variables. Most other PHP packages, if not already free of register global variables, should be in the process of eliminating them. PHP 5 and news of the withdrawl of register global variables have been out long enough that any actively maintained package should be well on its way to no longer using register global variables.

(Thanks to Lunarforum Member MrPhil for this Contribution!)