Converting PHP Associative Arrays to Variables
EDIT: Nick Ohrn pointed out that a function exists for doing this automatically. The following post is still a valid look at how this could be implemented if the functionality didn’t already exist, but it is better to use extract because it is likely more efficient.
Associative arrays are one of my favorite PHP features. They’re simple to use and easy to understand. Sometimes though, being able to reference the values of associative arrays with variables can be more convenient. Today I’m going to share a simple way to convert an associative array to variables.
OK, if you’re not sure what we’re trying to accomplish here, take a look at the following example.
$list = array( 'var1' => 'value1', 'var2' => 'value2' );
To reference the elements in the array, you’ll have to use the array key like this.
echo $list['var1']; //prints 'value1' echo $list['var2']; //prints 'value2'
What we’d like to do instead is reference the values using variable names like this.
echo $var1; //print 'value1' echo $var2; //print 'value2'
This is possible through what the PHP Manual calls ‘variable variables’. The idea is that the value of one variable is used as the name of another variable. Here’s an example.
$hello = 'world'; $$hello = 'howdy'; echo $world; //prints 'howdy'
Here, the value of $hello is analyzed and used as the name of the variable to which 'howdy' is assigned.
Now it’s not a big step to expand this to an associative array. Consider the following code.
$list = array( 'var1' => 'value1', 'var2' => 'value2' );
foreach ( $list as $key => $value ) { $$key = $value; }
echo $var1; //prints 'value1'
echo $var2; //prints 'value2'
So we’ve accomplished what we set out to do. I must caution you, though, about a couple of things which might trip you up.
First, make sure the keys are valid variable names. If you don’t you’ll run into problems when you execute the script.
Second, be very careful when using this with user input. For example, the following code is insecure.
// login.php
// checks the username and password in the GET request
$realuser = 'me';
$realpass = 'secret';
foreach ( $_GET as $key => $value ) { $$key = $value; }
if ( $user == $realuser && $pass == $realpass ) {
echo 'login correct';
} else {
echo 'login incorrect';
}
There are several problems here. First, we don’t know that $user and $pass have been initialized. We should check this before using them. Second (and more importantly) a cleverly generated request could let a user log in without a correct username/password. For example:
login.php?user=me&pass=wrong&realpass=wrong
When the script runs through the list of variables, it will assign a new value of wrong to $realpass. Because $realpass and $pass have the same value (as do $user and $realuser), the page will allow them to log in.
Here is a way to keep things a little safer by prefixing all the $_GET[] values.
// login.php
// checks the username and password in GET request
$realuser = 'me';
$realpass = 'secret';
foreach ( $_GET as $key => $value ) { ${'get_'; . $key} = $value; }
if ( isset( $get_user ) && isset( $get_pass )
&& $get_user == $realuser && $get_pass == $realpass ) {
echo 'login correct';
} else {
echo 'login incorrect';
}
Now the $_GET[] values are prefixed with get_ so they can’t interfere with other variables in the script. Additionally isset is used to ensure that the values of the variables has actually been set.
To use something like this, you’d still need to check for invalid variable names, but I won’t go into that for this example.
Nice try here, but you might want to take a look at
extract. Nothing wrong with the way you’re doing it, but the language has a built-in construct that accomplishes what you’re doing manually with a for loop and quite a bit of overhead.The “variable variables” must be interpolated by the PHP interpreter in order to get the correct results and that causes the interpreter to take a while to do what it needs to do (although a “while” might be just extra milliseconds depending on the size of the array, you’d have to profile to be sure.
Wow, I’m not sure how I missed that. Thanks for pointing it out. I’ll edit the post so I don’t lead anyone else astray.
Don’t blame yourself too much. It happens from time to time. There are plenty of instances in the past few years where I’ve done something completely ridiculous, only to find out that I should have been using a library function call or a built-in language construct. It’s just part of the learning process.
Nevertheless, a good explanation of variable variables – something else many PHP developers are unaware of and, most certainly, most beginners have never heard of. I find variable variables useful in many situations.