Каково реальное использование переменных переменных?
Переменные переменные выглядят довольно круто, но я не могу придумать сценарий, в котором можно было бы использовать их в производственной среде. Каким будет такой сценарий? Как они были использованы?
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= '';
Я надеюсь, что это помогает