In PHP parlance a variable variable is a variable that holds a the name of another variable of any data type. In other words, a variable variable is an example of dynamic typing, or duck typing. Dynamic typing and duck typing are two features that get a lot of attention in object oriented languages like Ruby and Python because they’re useful for doing magic tricks. Rather than muddy the water be talking of this mysterious thing called magic, I’ll call it what it is: dynamic typing.
Although dynamic typing is one of PHP’s most useful features, beginning PHP programmers can find it confusing. The terminology itself—variable variables—is a little too clever to be useful. Moreover, when variable variables are discussed, they are usually shown in non-productive examples, like this:
1 $place = 'The Big Apple'; // $place can be written ${place}
2 $holder = 'place'; // Holds the name of the $place variable
3 echo $$holder; // ==> The Big Apple
How it works
In line 1 we assign the value “The Big Apple” to $place.
In line 2 we assign $holder the value ‘place.’
But what’s going on with the ‘$$‘ in line 3? This bit of syntax is where PHP processes the variable variable.
Let’s consider how PHP handles line 3.
3 echo $$holder;
First, we need to remind ourselves that PHP parses each line from right to left. When PHP encounters the ‘$$‘, it processes the rightmost ‘$’ first. We can illustrate this by rewriting our code to wrap the first occurence in braces:
${$holder} ~ ${${holder}} ~ $$holder // these three forms are equivalent
We can take this one step further and do variable substitution on $holder. In expressions, PHP replaces ‘$‘ variables with the values they refer to. In this case, ‘$holder‘ will be dereferenced and the value “place” will replace it. Now our code looks like this:
${'place'}
We still have the leftmost ‘$‘ and the ‘place‘ within the braces, which becomes:
$place
A synopsis of the process would look like this:
6 5 4 3 2 1
'The Big Apple' ~ $place ~ ${'place'} ~ ${$holder} ~ ${${holder}} ~ $$holder
Although this example shows the process of using variable variables, it doesn’t give us a reason to use them in our programs. To see how to make use of variable variables, we need to see a few more examples.
What’s in a Variable?
In a dynamically typed language, it turns out that variables don’t really hold anything in particular. PHP variables simply point to something stored at some area of memory in your program. That something might be a string, a number, a filehandle, or any other kind of object. Whatever happens to be at the target location is available through the variable. Because variables are able to refer to any kind of PHP data type, we can do some of those so-called magical things quite conveniently.
Variables Used as Functions
In the following example, we will use variables to refer to the names of some functions.
Let’s assume for a moment that we have to create an HTML table using a multi-dimensional array that contains arrays of names.These arrays could be created by a query to a database, or they could be created from any other source. Our script will not care where the arrays came from. Our job is to put the names in each array into an HTML row, with each element encased in <td> tags, and the tags for each row encased in <tr> tags, all within containing <table> tags.
The array looks like this:
<?php
/** An array of names in an orderly format, as from a database. */
$names = array(
array('al', 'bob','cary','dave','ed'),
array('fred', 'george','harriet','isadore','jake'),
array('karen', 'louise','marion','ned','olive'),
array('paul', 'quincy','rhoda','sarah','terry'),
array('unknown', 'vera','whitey','xavier','zed')
);
?>
There are lots of ways to solve this problem, but for this example we’ll use variable variables to process a list of functions.
<?php
/**
* Create some HTML function
*/
/** Creates <td> elements. */
function td($array) {
$out = array();
foreach($array as $k => $a) {
$out[] = " <td>" . implode("</td>\n <td>", $a) . "</td>\n";
}
return $out;
}
/** Creates <tr> elements using <td> elements. */
function tr($tds) {
$out = '';
foreach($tds as $row) {
$out .= " <tr>\n" . $row . ' </tr>'."\n";
}
return $out;
}
/** Creates a table using <tr> elements. */
function table($trs){
return '<table>' . "\n" . $trs . '</table>' . "\n";
}
/**
* The function names are entered in the array
* in the order that they will be executed.
*/
$funcs = array('td','tr','table');
/** Feed the $input array to the functions. */
$input = $names;
foreach($funcs as $function) {
$input = $function($input);
}
?>
<h1>Names</h1>
<?php echo $input ?>
The output:
<h1>Names</h1>
<table border>
<tr>
<td>al</td>
<td>bob</td>
<td>cary</td>
<td>dave</td>
<td>ed</td>
</tr>
<tr>
<td>fred</td>
<td>george</td>
<td>harriet</td>
<td>isadore</td>
<td>jake</td>
</tr>
<tr>
<td>karen</td>
<td>louise</td>
<td>marion</td>
<td>ned</td>
<td>olive</td>
</tr>
<tr>
<td>paul</td>
<td>quincy</td>
<td>rhoda</td>
<td>sarah</td>
<td>terry</td>
</tr>
<tr>
<td>unknown</td>
<td>vera</td>
<td>whitey</td>
<td>xavier</td>
<td>zed</td>
</tr>
</table>
Run this code yourself to see the little table that pops out of this code. You can see that each function in the array is run as when $func refers to it. The value passed into the function is the value returned by the previous function. By the way, print() and echo() are not functions, so this technique will not work with them.
Next
In the next PHP Good Part we’ll extend variable variables a little further to create pretty URLs.
Until then, keep hacking…
–Douglas Putnam