Каково реальное использование переменных переменных?

Переменные переменные выглядят довольно круто, но я не могу придумать сценарий, в котором можно было бы использовать их в производственной среде. Каким будет такой сценарий? Как они были использованы?

7 ответов

Решение

Я предполагаю, что его цель - позволить начинающим программистам динамически изменять данные без использования "сложных вещей", таких как составные типы (массивы и объекты).

Я никогда не использую их.

Переменная переменная по сути является массивом (карта / словарь). Ниже приведены эквивалентные идеи:

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

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

Таким образом, если вы поместите ваши "переменные переменные" в родительский массив, вы можете покончить с ними.

Я видел, как люди используют переменные свойства внутри классов:

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

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

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

Но опять же, вы можете использовать массив:

<?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;
?>

И вне классов:

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

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

Поэтому вам никогда не придется использовать переменные переменные или свойства переменных при написании собственного управляемого кода. Мое личное предпочтение - никогда не использовать переменные переменные. Я иногда использую свойства переменных, но предпочитаю использовать массивы, когда буду получать доступ к данным таким образом.

Лично я использую их довольно часто. Все вызовы следующих типов используют переменные-переменные:

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

Поэтому каждый раз, когда вы делаете динамический вызов метода / функции, вы используете переменные-переменные...

Обычное использование для этого - доступ к защищенным свойствам через __get магический метод. Я часто видел следующее:

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

Который по определению использует переменные переменные для обеспечения доступа для чтения к защищенным членам...

Я никогда не использовал $$var синтаксис (и не думаю, что когда-либо буду). Я видел, как он использовал для доступа к глобальным переменным по имени global $$name; echo $$name;но то же самое можно сделать с $_GLOBALS[$name] синтаксис, так что это не хороший вариант использования (не говоря уже о том, что использование глобальных переменных обычно считается плохой практикой)...

Подумайте об этом для использования в системе шаблонов, где вы используете файлы PHP и вам необходимо установить переменные:

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;
}

Теперь, предполагая, что вы использовали эти имена переменных в своем шаблоне, вы можете вызвать его и передать в него переменные для использования.

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

Тогда в вашем шаблоне:

Hello <?php echo $name; ?>!

Я нашел это полезным в одном сценарии. У меня были результаты API YouTube в формате JSON, вот так

 $obj->media$title => Video title

Так что я использовал это как

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

Так у меня это сработало:)

Я знаю, что это старая тема, и переменные переменные не очень используются. На самом деле, я не удивлюсь, если в будущих версиях он станет устаревшим.

Но я нашел его очень полезным в качестве альтернативы оператору switch, гораздо более чистого, простого и краткого решения. Кроме того, кажется, что он работает более эффективно, чем оператор переключения.

Итак, это:

      class AlterSwitch{

    public static function the_case($option){

        $dirname = dirmane(__DIR__);

        switch ($option){
            case 'root':
                $section = $dirname . '/templates/root.html';
                break;
            case 'head':
                $section = $dirname . '/templates/head.html';
                break;        
            case 'item_cont':
                $section = $dirname . '/templates/item_cont.html';
                break;
            case 'item':
                $section = $dirname . '/templates/item.html';
                break;
    }
    return $section;

}

Можно превратить в это:

      class AlterSwitch{

    public static function the_case($option){

        $dirname = dirmane(__DIR__);

        $root = $dirname . '/templates/root.html';
        $head = $dirname . '/templates/head.html';
        $item_cont = $dirname . '/templates/item_cont.html';
        $item = $dirname . '/templates/item.html';

        if($$option!==null){
            # Variable variable is the parameter and returns the Variable of this class
            return $$option;
    } 
    return "File not found";  
    }

}


// Instantiate e.g.
// For both classes
// returns $section - $head

AlterSwitch::the_case('head'));

Я в основном использую его, чтобы уменьшить копирование-вставку при очистке данных get/post в начале php-файла: он делает очищенные переменные с правильными именами:

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

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

вместо всех этих строк:

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= '';

Я надеюсь, что это помогает

Другие вопросы по тегам