2017-08-24 90 views
8

我刚刚刚介绍了PHP中动态变量的概念。对我来说,似乎在程序中使用动态变量会使其难以阅读/遵循。为什么在PHP或其他语言中使用动态变量(变量变量)

任何人都可以向我解释的好处和/或分享一个真正简单的现实世界的例子,当PHP中的动态变量可能需要?

如果你想知道什么动态变量,以及它们是如何工作的检查this question

+5

它们通常被称为变量变量;只是因为它们存在,并不意味着你必须使用它们......通常我会建议不要使用它们,因为总会有更好的替代方案 –

+0

在我看来,它使得它难以阅读/遵循。 –

+0

基于很多问题,人们在这里试图弄清楚如何使用变量变量,他们通常应该命名数组键,而不是创建不同的变量。 –

回答

6

我已经投票决定关闭这个问题,它是主观的基础上(投自缩回),但细想起来,我想我可以给出一个客观的答案。

静态变量名称是一个字符序列,表示一个令牌,底层引擎将其用作标签来标识该变量代表的值(非常非常规的描述)。

“字符序列”是一个字符串。 A 字符串是表示字符串的表达式。所以从这里可以推断,任何表示字符串的表达式都应该足以代表引用变量的标记。并且该表达式本身可以分配给一个变量,并从那里获得动态变量名称。

但这不是你问的。你问:为什么?

这不是语言的实现者回答这样的问题。他们的工作是通过他们的语言提供统一和可预测的编程接口。它是uniform能够通过一个表达式来表示一个字符序列,而该表达式又可以用一个变量表示。任务完成。

主观上,我可能会看到从外部源导入某些数据的位置,甚至数据的模式也是动态的。人们可能想用某种通用对象方式来表示它,并且从那里引出对象的属性名称也可能是动态的。这对于解决这个问题是否是一个好的方法是完全主观的,并且直接取决于开发者的判断以及代码审查期间他们的同行的判断。

另一个例子可能是你继承了一些“需求必须”和使用动态命名的粗糙的意大利面条代码 - 无论出于何种原因 - 可能是一个好方法。

PHP的负担终止于提供编写代码的机制;它不会说代码的设计质量。这就是代码审查的目的。

+1

好的答案!感谢您花时间解释。你有一些伟大的观点! – ScottyG

+1

当/如果这个问题产生一个有趣的答案时,自动关闭问题有时候会更好。 –

4

A variable variable,只是reflection的另一种形式。你基本上在问:“如果你在运行之前不知道,为什么要改变一个变量?”。

尽管技术上不尽相同,但您可以将variable variable看作是另一种hash table(或在PHP中为array)。大多数variable variables可能会被重写为hash table,您不会感到惊讶。但是如果你需要在运行前后使用变量,那么hash table甚至可能更难处理。

一个简单的用例可能是用户可以更改的设置。请记住,下面的例子是不安全的,但证明了它的目的。

<?php 
/* 
Simple way, if you have a limited amount of settings 
*/ 
$settings = array(); 
$settings["allowAccess"] = 1; 
$settings["allowModify"] = 1; 
$settings["allowDelete"] = 0; 

if ($result = $mysqli->query("SELECT `allowAccess`, `allowModify`, `allowDelete` FROM `user_settings` LIMIT 1")) 
{ 
    $row = $result->fetch_array(MYSQLI_ASSOC); 
    $settings["allowAccess"] = $row["allowAccess"]; 
    $settings["allowModify"] = $row["allowModify"]; 
    $settings["allowDelete"] = $row["allowDelete"]; 
} 

/* 
Now consider you have a thousand settings and you dont want to write out every setting manually. 
*/ 
if ($result = $mysqli->query("SELECT * FROM `user_settings` LIMIT 1")) 
{ 
    $row = $result->fetch_array(MYSQLI_ASSOC); 
    foreach($row as $key => $val) { 
     $settings[$key] = $val; 
    } 
} 

/* 
Both options work, but everytime you want to use a setting you have to use something like below 
*/ 

if ($settings["allowAccess"] && $settings["allowModify"] && $settings["allowDelete"]) { 
    unlink($somefile); 
} 

/* 
Perhaps you would rather write 
*/ 

if ($allowAccess && $allowModify && $allowDelete) { 
    unlink($somefile); 
} 

/* 
Then you can use 
*/ 
if ($result = $mysqli->query("SELECT * FROM `user_settings` LIMIT 1")) 
{ 
    $row = $result->fetch_array(MYSQLI_ASSOC); 
    foreach($row as $key => $val) { 
     //if you use extract, all columns are extracted, unless you drop them first. But perhaps you need those for something else. 
     //now I extract the columns that start with allow and keep the columns like id, created, modified, etc. without the need to specify each column manually, which makes it easier if you ever decide to add another setting column. You don't need to update this part of the code. 
     if (substr($key,0,5)=='allow') { 
      $$key = $val; //$key = 'allowAccess', $$key == $allowAccess = $val; 
     } 
    } 
} 
?> 

这只是一个例子,我发现在XHTML sanitizer for MediaWiki另一个例如通过Brion Vibber。他在自己的代码中使用了很多数组,并且有一次他需要将所有数组全部翻转。他使用下面的代码:

<?php 
$vars = array('htmlpairs', 'htmlsingle', 'htmlsingleonly', 'htmlnest', 'tabletags', 
       'htmllist', 'listtags', 'htmlsingleallowed', 'htmlelements'); 
foreach ($vars as $var) { 
    $$var = array_flip($$var); 
} 

?> 

现在很明显,他可以写下面的代码,但是真的更容易阅读?

<?php         
$htmlpairs = array_flip($htmlpairs); 
$htmlsingle = array_flip($htmlsingle); 
$htmlsingleonly = array_flip($htmlsingleonly); 
$htmlnest = array_flip($htmlnest); 
$tabletags = array_flip($tabletags); 
$htmllist = array_flip($htmllist); 
$listtags = array_flip($listtags); 
$htmlsingleallowed = array_flip($htmlsingleallowed); 
$htmlelements = array_flip($htmlelements); 
?> 

这也引入了另一个用例:如果我想动态地决定哪些数组要翻转怎么办?在variable variable的方式,我可以将项目推到阵列上,并在时间到来时将它们翻转。以“正常”方式,我需要一个switchif循环访问阵列,然后手动添加每个选项。

+0

有趣的例子。它引导我到另一个问题,但为什么会使用数组翻转? – ScottyG

+1

我在[此回答](https://stackoverflow.com/a/16521079/434949)中使用它来比较PHP中两个字符串的部分相似性。基本上,如果数组包含某个值,则必须检查很多次才使用它。通过翻转一次,您就可以使用'array_key_exists'而不是不断循环整个数组来查看它是否包含该值。但是,尽管这个例子使用'array_flip',你可以在想要做很多变量的时候使用'variable variables',或者当你想动态地分配你想要做的变量。 –

+0

'foreach($ row as $ key => $ val){$$ var = array_flip($$ var); }'提取($ row)'更简单? – symcbean