为什么在PHP或其他语言中使用动态变量(变量变量)

时间:2017-08-24 16:23:01

标签: php performance optimization coding-style php-7

我刚刚介绍了PHP中动态变量的概念。对我来说,似乎在程序中使用动态变量会使其难以阅读/遵循。

有人可以向我解释一下这些好处和/或分享一个真正简单的现实世界的例子,说明何时可能需要PHP中的动态变量?

如果您想知道动态变量是什么以及它们如何工作,请查看this question

2 个答案:

答案 0 :(得分:6)

我已经投票决定关闭这个问题(自收回后投票),因为它是主观的,但经过反思,我认为我可以给出一个客观的答案。

静态变量名称是一个字符序列,表示底层引擎用作标签的标记,用于标识变量所代表的值(非常非常外行的描述)。

A"字符序列"是一个字符串。 字符串是表示字符串的表达式。因此,从那里可以理解,任何表示字符串的表达式都应该足以表示引用变量的标记。并且该表达式本身可以分配给变量,并从那里获得动态变量名称。

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

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

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

另一个例子可能是你已经继承了一些伪劣的意大利面条代码,其中需要"需要"并且使用动态命名 - 无论出于何种原因 - 可能是一种很好的方法。

PHP的负担以提供编写代码的机制而告终;它没有说出所述代码的设计质量。这是代码审查的目的。

答案 1 :(得分:4)

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来循环数组,然后手动添加每个选项。