How to use variable variables in PHP

One of the biggest time-savers in PHP is the ability to use variable variables.  While often intimidating for newcomers to PHP, variable variables are extremely powerful once you get the hang of them.

Variable variables are just variables whose names can be programatically set and accessed.  For example, the code below creates a variable called $hello and outputs the string “world”.  The double dollar sign declares that the value of $a should be used as the name of newly defined variable.

<?php
$a = 'hello';
$$a = 'world'
echo $hello;
?>

When I started with PHP about 10 years ago, everyone was still using global variables.  That meant that anything you passed as a GET variable could be used as a local variable.  It was very convenient, but unfortunately not very secure.  For me, typing $HTTP_GET_VARS[‘count’] just wasn’t as fun as being able to use $count.  I found myself adding long declaration lists to the top of my files that did nothing but convert my GET/POST variables to local variables.  My code started to look like this:

<?php
$salutation = $HTTP_GET_VARS['salutation'];
$fname = $HTTP_GET_VARS['fname'];
$lname = $HTTP_GET_VARS['lname'];
$email = $HTTP_GET_VARS['email'];
...
?>

Do that for a couple dozen variables and you’ll start telling yourself there has to be a better way.  Nowadays you can use $_GET instead of $HTTP_GET_VARS, but the better solution is to use variable variables. Now my code looks more like this:

<?php
// create an array of all the GET/POST variables you want to use
$fields = array('salutation','fname','lname','email','company','job_title','addr1','addr2','city','state',
                'zip','country','phone','work_phone');

// convert each REQUEST variable (GET, POST or COOKIE) to a local variable
foreach($fields as $field)
    ${$field} = sanitize($_REQUEST[$field]);
?>

This has several benefits.  I reduced 14 lines of code down to 3.  I now have one place to sanitize all my external input. And if I ever decide to change a variable name, I have one less place in my code to fix.

This benefit of this technique increases as you use the $fields array throughout your code.  I now utilize the $fields array when saving my form data to the database.  I use it for loading existing user values from the database.  I use it for passing my form fields back to smarty:

<?php
$form = array();
foreach($fields as $field)
    $form[] = $_REQUEST[$field];
$smarty->assign('form',$form);
?>

Variable variables have become one of my favorite features of PHP. They’ve allowed me to tighten up a lot of my code and made it a lot more maintainable.

Have you done anything cool with variable variables?  What other PHP tricks have revolutionized the way you write code?

  • Larry McKeogh

    Josh, I am just getting below the surface of PHP. The use of variable variables makes sense in the way I have seen PHP to behave, just hadn't gotten to the point of using them.
    Useful information that I will experiment with. Thanks for sharing.

  • Humm – If you could somehow prevent the security risks, you could just do:
    foreach ( $_POST as $varname => $postitem )
    {
    $a = $varname;
    $$a = $postitem;
    }

  • Josh (or anyone) –
    If you have any comments on the above would appreciate hearing them. The more I thought about it, you can really do the same security precautions using the above as you would any post variables. Of course, an intruder could create their own variable name, which is a little weird, but it would be just as easy to sanitize a variable name as it would its contents.

    • That's basically the same as turning global variables on in your php.ini file — convenient, but not safe. Major security implications arise when you give people the ability to set any local variables they want. For example, what would happen if they set $i = 50, or worse, figured out that you use the variables $user_id and a boolean called $logged_in? Attackers could sign in as anyone they wanted just by passing in the various GET variables. I guess you could try and sanitize the variable names later, but it's always easier to stop bad data at the door than allowing it in and being continually being suspicious of it.

      In other words, I know it's temping, but don't do it. It's not good practice.

  • Guess you're right :0(

  • fractalbit

    Hello, i recently discovered your blog and i find the stuff you post very useful. This little tutorial is very useful and i am eager to try it out. But reading it, it came to my mind an old problem i had. This may or may not be relevant to the above article but you could probably advise me.

    What i want to do is to build a simple function called debug that will get a variable (eg. $problem = 'solved!') and output:

    <hr />
    variable name: problem | variable value: solved!
    <hr />

    Of course the only part i cant figure out is how to print the name of the variable as everything else is super easy. Is there a simple function i am missing or is it more complicated?

    • Yeah, that's actually a great example of how to use variable variables:

      function debug($var_name) {
      global ${$var_name};
      echo "variable name: $var_name | variable value: ".${$var_name};
      }

      $problem = "solved!";
      debug("problem");

      A couple things to notice about this example. 1) You need to declare the variable as global because of the way name-spacing works in PHP and 2) you need to pass in the name of the variable (problem instead of $problem).

    • Yeah, that's actually a great example of how to use variable variables:

      function debug($var_name) {
      global ${$var_name};
      echo "variable name: $var_name | variable value: ".${$var_name};
      }

      $problem = "solved!";
      debug("problem");

      A couple things to notice about this example. 1) You need to declare the variable as global because of the way name-spacing works in PHP and 2) you need to pass in the name of the variable (problem instead of $problem).

      • Thanks Josh, to understand it better i tried to reconstruct the function and improve on it. Here is what i ended up with:

        function debug($variables){
        /*
        Enter the variable names you wish to debug as a string separated by commas
        It will print the variable name and their respective values like: $varname = value
        The variable values can be strings, integers, floats, arrays and possibly objects? (didn't test it)
        For example ….

        $thanks = 'to Josh Fraser';
        $fruits = array("apple", "orange", "cherry");
        debug("thanks, fruits");

        will print…

        ————————————————————————
        Debug info
        ————————————————————————
        $thanks = to Josh Fraser
        $fruits = Array ( [0] => apple [1] => orange [2] => cherry )
        ————————————————————————
        */

        echo '<hr />Debug info';
        $var_array = explode(",", $variables);
        foreach($var_array as $var){
        $var = trim($var);
        global $$var;
        $results[] = '$' . $var . ' = ' . print_r($$var, TRUE) . '
        ';
        }
        echo '<hr />' . implode("", $results) . '<hr />';
        }

        • hmmm, it doesn't appear very well, it removed tabs and br actually appears as a new line instead of printing it. Is there a special tag i should use when posting comments? (ex. {pre}code{/pre} )

        • hmmm, it doesn't appear very well, it removed tabs and br actually appears as a new line instead of printing it. Is there a special tag i should use when posting comments? (ex. {pre}code{/pre} )

        • hmmm, it doesn't appear very well, it removed tabs and br actually appears as a new line instead of printing it. Is there a special tag i should use when posting code? (ex. {pre}code{/pre} )

          P.S. You added the ability to edit comments? 🙂

        • hmmm, it doesn't appear very well, it removed tabs and br actually appears as a new line instead of printing it. Is there a special tag i should use when posting code? (ex. {pre}code{/pre} )

          P.S. You added the ability to edit comments? 🙂 (Or is it because i am now registered to intenseDebate?)

          • Yeah, the formatting is a bit wonky. Sorry about that. I use a service called IntenseDebate for my comments. They give me a bunch of awesome features but it means I have to deal with a couple small issues like formatting and the inability to edit a comment. Totally worth the trade-off if you ask me.

  • robert

    I came to your post looking for an aswer for my PHP class assigment. Proffesor asked, 3.When is better to use a local variable? I can't seem to find an aswer for any. Any help will be great.

  • Variables are used for storing values, like text strings, numbers or arrays. When a variable is declared, it can be used over and over again in your script. thanks for sharing the informative post.

  • dmjones

    I wanted to use this avenue in order to populate private variables of a class using an array as input. However, the values don't seem to stay or aren't even assigned to the private vars. Any ideas?

    class aClass {
    private $_fruitA;
    private $_fruitB;
    private $_fruitC;

    public function set($inputArray)
    {
    foreach ($inputArray as $key=>$val)
    {
    $var = "this->_{$key}";
    $$var = $val;

    //prints nothing
    print "this->_$key: ".$this->_fruit."n";

    //prints the $val assigned in $inputArray
    print "$$var: ".$$var."nn";
    }
    }
    }

    $fruit = new aClass();
    $fruit->set(array('fruitA' => 'apple', 'fruitB' => 'banana'));

  • dmjones

    The alternative was suggested and works well

    $this->{'_' . $key} = $val;

  • bayard barnslee

    The presence of variable variables in code is a flashing red light that the programmer was either 1) a hack and a lazy one at that, or 2) had to work with a mess left by a lazy hack and had no time to refactor it so variable variables are not needed.

    In both cases the hack is using variable variables like a Looney Tunes cartoon character uses an Acme Portable Hole — whenever they realize they're backed into a corner, they resolve the dilemma by dropping a Portable Hole and bailing or having the bad guy disappear in it. Problem solved.

    Variable variables in the code is almost always the sign of a clever amateur who is in way over his head but is too full of himself to realize that.