13

In PHP there's a functionality officially called "Variable Variables" where one can assign variable variables. A variable variable takes the value of one variable as the name for a new variable! For example:

$name='Joe';
$$name='Smith'; // could also be written as ${$name}='Smith'

The first variable $name contains the value 'Joe', while the second is variable named $Joe with the value 'Smith'. Take into account that PHP variables are case-sensitive!

I've never used this functionality and do not see the purpose for that. Could someone explain to me where this functionality could be exploited as a good practise?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
sbrbot
  • 6,169
  • 6
  • 43
  • 74

4 Answers4

12

Sometimes we need software that is extremely flexible and that we can parametrize. You have to prepare the whole thing, of course, but part of it just comes from user input, and we have no time to change the software just because the user needs a new input.

With variable variables and variable functions you can solve problems that would be much harder to solve without them.

Quick Example:

Without variable variables:

$comment = new stdClass(); // Create an object

$comment->name = sanitize_value($array['name']);
$comment->email = sanitize_values($array['email']);
$comment->url = sanitize_values($array['url']);
$comment->comment_text = sanitize_values($array['comment_text']);

With variable variables

$comment = new stdClass(); // Create a new object


foreach( $array as $key=>$val )
{
    $comment->$key = sanitize_values($val);
}
Faiz Ahmed
  • 1,083
  • 8
  • 16
  • 2
    Excellent example, if $array is $_POST even better! – sbrbot Aug 31 '14 at 22:07
  • 1
    @Faiz Ahmed I don't see where you're utilising the variable variable? Looks like you're just iterating over an array and passing key=>value pairs. – user3796133 Jun 02 '19 at 13:30
  • @user3796133 the variable variable is `$comment->$key` where `$key` is substituted for the object property name. This is the only way to retrieve a dynamically specified object property. You'll notice in the "Without variable variables" section that there is no extra `$` before the property name after the arrow. – sfscs Jun 04 '19 at 19:07
  • 1
    Why not just `$comment = (object) \array_map('sanitize_value', $array);`? – phylogram Dec 15 '20 at 12:21
1

This has some uses when referencing variables within classes, and there are some cases where these can actually be required (such as in __get(), __set(), __isset(), and __unset()). However, in most cases it is unwise to use them on global variables.

Be aware that you should NEVER directly accept end-user input when it comes to variable variables. Instead a wrapper function should be used to ensure that only specific inputs are allowed.

In most cases, variable variables are not required, and it is recommended that you avoid them when possible.

Nicholas Summers
  • 4,444
  • 4
  • 19
  • 35
1

You can use for something like

$labels = array( 'first_name" => 'First Name", 'middle_name" => 'Middle Name", 'last_name" => 'Last Name", 'phone" => 'Phone");
        foreach($labels as $field => $label)
        {
        echo '<div id='field'><label for='$field'>$label</label>
        <input id='$field' name='$field' type='text' value='".$$field."' /></div>";       
        }

In my opinion is bad old school...

SylarBg
  • 121
  • 1
  • 2
0

According to @Faiz answer (which I accepted as the formal answer to my question) I created the following sample example.

If I had the class Customer:

class Customer
{
  public $firstname;
  public $lastname;
  public $country;
  public $gender;
  ...
}

and the web HTML form with INPUT/SELECT fields having names 'firstname','lastname','country', 'gender'...

<form action="..." method="post">
  <input type="text" name="firstname" value="" />
  <input type="text" name="lastname" value="" />
  <select name="country">
    <option value="AL">Albania</option>
    <option value="BE">Belgium</option>
    <option value="HR">Croatia</option>
    ...
  </select>
  <input type="radio" name="gender" value="M" />Man
  <input type="radio" name="gender" value="F" />Woman
  ...
  <input type="submit" value="Submit" />
</form>

usually in my action script I would map these form fields into class variables one by one as:

$Customer=new Customer();
$Customer->firstname=$_POST['firstname'];
$Customer->lastname=$_POST['lastname'];
$Customer->country=$_POST['country'];
$Customer->gender=$_POST['gender'];
...
$Customer->create();

But using variable variables I can easily map all associative array values (there could be a lot of them which is error prone) into class variables using the following one line foreach loop;

$Customer=new Customer();
foreach($_POST as $key=>$value) $Customer->$key=$value;
$Customer->create();

Note: For the sake of answer (logic) simplicity and clearness I omitted $_POST values sanitization.

sbrbot
  • 6,169
  • 6
  • 43
  • 74
  • The great thing is that the same principle can be used for mapping between associative database row elements and class variables! – sbrbot Sep 01 '14 at 11:02