What's an actual use of variable variables?

2019-01-09 10:34发布

问题:

Variable variables seem pretty cool, but I can't think of a scenario where one would actually use them in a production environment. What would such a scenario be? How were they used?

回答1:

Its purpose, I guess, is to allow novice programmers to dynamically change data without using "complicated stuff" like composite types (arrays and objects).

I never use them.



回答2:

A variable variable is essentially an array (map/dictionary). The following are equivalent ideas:

<?php
$foo = array('a' => 1);
$bar = 'a';
echo $foo[$bar]."\n";

$foo_a = 1;
$bar = 'a';
$vv = "foo_$bar";
echo $$vv."\n";
?>

Thus if you wrap your "variable variables" into a parent array, you can do away with them.

I've seen people use variable properties inside classes:

<?php
class Foo
{
  private $a = 1;

  public function __get($key)
  {
    if (isset($this->$key)) return $this->$key;
  }
}

$foo = new Foo();
echo $foo->a;
?>

But again, you could use an array:

<?php
class Foo
{
  private $props = array('a' => 1);

  public function __get($key)
  {
    if (array_key_exists($key, $this->props))
      return $this->props[$key];
  }
}

$foo = new Foo();
echo $foo->a;
?>

And outside classes:

<?php
class Foo
{
  public $a = 1;
}

$foo = new Foo();
$prop = 'a';
echo $foo->{$prop};
?>

So you never "have" to use variable variables or variable properties when writing your own controlled code. My personal preference is to never use variable variables. I occasionally use variable properties, but prefer to use arrays when I'll be accessing data in that way.



回答3:

Personally, I use them fairly often. All calls of the following types use variable-variables:

$foo->$bar = 'test';
$foo->$bar();
$bar();

So any time you do a dynamic method/function call, you're using variable-variables...

A common use for this is accessing protected properties via the __get magic method. I've seen the following quite often:

public function __get($name) {
    return isset($this->$name) ? $this->$name : null;
}

Which by definition is using variable variables to provide read-access to the protected members...

I've never directly used the $$var syntax (and don't think I ever will). I have seen it used to access global variables by name global $$name; echo $$name;, but the same thing can be done with the $_GLOBALS[$name] syntax, so that's not a good use-case (not to mention that using global variables is usually seen as bad practice)...



回答4:

Think of it for use in a template system where you are using PHP files and need to set in variables:

function fetch_template($file, $vars){
    $ret = 'File not loaded.';
    if(file_exists(TEMPLATE_PATH.$file)){
        //could do this with extract() but I am showing you
        foreach($vars as $varName => $value){
            ${$varName} = $value;
        }
        ob_start();
        include(TEMPLATE_PATH.$file);
        $ret = ob_get_contents();
        ob_end_clean();
    }
    return $ret;
}

Now assuming you used these variable names in your template, you could call it and pass variables into it for use.

echo fetch_template('hi_there.tpl', array('name'=>'JJ'));

Then in your template:

Hello <?php echo $name; ?>!


回答5:

I found it useful in a single scenario. I was having YouTube API results in JSON format, like this

 $obj->media$title => Video title

So I used it like

$mt = 'media$title';
$obj->$mt ;

So it worked for me here :)



回答6:

I mainly use it to reduce copy-paste in sanitizing get/post data in the begining of a php file: It makes sanitized variables with the proper names:

$fields=array('age','name','gender','email','username');

foreach($fields as $field) {
    if (empty($_REQUEST[$field] === false)
        ${$field} = sanitize($_REQUEST[$field]);
    else
        ${$field} = '';
}

instead of all these lines:

if (empty($_GET['age']) === false) 
    $age= sanitize($_GET['age']);
else
    $age= '';

if (empty($_GET['name']) === false) 
    $name= sanitize($_GET['name']);
else
    $name = '';

if (empty($_GET['gender']) === false) 
    $gender= sanitize($_GET['gender']);
else
    $gender= '';

if (empty($_GET['email']) === false) 
    $email= sanitize($_GET['email']);
else
    $email= '';

if (empty($_GET['username']) === false) 
    $username= sanitize($_GET['username']);
else
    $username= '';

I hope it helps