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;
}
}
}
?>
这只是一个例子,我在Brion Vibber 的XHTML sanitizer for MediaWiki 中找到了另一个例子。他在他的代码中使用了很多数组,有一次他需要将它们全部翻转。他使用了下面的代码:
<?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 方式中,我可以将项目推入数组并在时机成熟时翻转它们,在“正常”方式中,我需要switch 或if 来循环遍历数组,然后添加每个选项手动。