我已经在 PHP 中进行了一段时间的开发,但我仍然没有必须使用可变变量的任务。谁能给我举例说明使用它们是个好主意吗?还是只是为了好玩而将它们包含在语言中?
8 回答
我通常会在代码难闻的地方找到它们。也许引用静态配置变量等...但是为什么通常的关联数组不是更好的解决方案。似乎是一个等待发生的安全漏洞。
我想您也许可以在模板中有效地使用它们。
永远不要使用它们;“数组”总是一个更好的解决方案。
首先,如果您将用户输出用于这些目的,这将是一个巨大的安全问题。内部是这里唯一有效的用途。
鉴于此,我想它用于循环各种变量或将变量作为参数发送。
foreach($name in array('_GET','_POST','_REQUEST')) {
array_map('stripslashes',$$name);
}
我不得不使用它们的一种情况是 URI 处理,尽管这种技术可能已经过时了,而且我承认我已经很长时间没有使用它了。
假设我们要从格式中的脚本中提取 URI domain.tld/controller/action/parameter/s
。我们可以使用以下命令删除脚本名称:
$uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['REQUEST_URI']);
要从中提取控制器、操作和参数值,我们将不得不使用路径分隔符“/”来分解字符串。但是,如果我们有前导或尾随分隔符,我们将在爆炸时得到空数组值,因此我们应该从字符串的开头和结尾修剪它们:
$uri_string = trim($uri_string, '/');
我们现在可以将路径分解成一个数组:
$uri_data = explode('/', $uri_string);
$uri_data[0]
现在包含我们的控制器名称,$uri_data[1]
包含操作名称,以及数组中的值,超出这些参数是应该传递给操作方法的参数。
$controller_name = $uri_data[0];
$action_name = $uri_data[1];
因此,既然我们有了这些名称,我们就可以将它们用于许多事情。如果您将控制器保存在相对于站点根目录的非常特定的目录中,则可以将此信息用于require_once
控制器类。此时,您可以实例化它并使用变量变量调用它:
$controller = new $controller_name();
$controller->{$action_name}(); // Or pass parameters if they exist
在这种方法中需要注意很多安全问题,但这是我见过的一种利用可变变量的方法。
免责声明:我并不是建议您实际使用此代码。
我找到了一个很好的..
$php = "templates/php/default.php";
$html = "templates/html/default.php";
$css = "templates/css/default.php";
$js = "templates/js/default.php";
现在我让用户说出他想要哪个文件 php 或/和 html..
$userarray = array("php", "css");
foreach($userarray as $file){
var_dump($$file);
}
输出:
模板/php/default.php
模板/css/default.php
我在尝试对这样的静态变量进行限定范围时遇到了
self::$file;
这个问题,然后我记得我可以使用变量变量
self::$$file;
,这些变量将被解释为self::$php;
语言包含您不应该与 bargepole 接触的功能并不少见(我什至不久前问过一个关于它的问题),而变量变量可能是属于这一类的那些结构之一。仅仅因为一种语言包含一个特性并不意味着你必须使用它。
有时他们可能会解决问题(毕竟递归在实践中很少使用,但没有人会争辩说这不是必要的构造),但总的来说,任何语言特性都会掩盖你的代码正在做什么,并且变量变量肯定会落入这一类,应格外谨慎对待。
除非您正在使用多深度变量(如果您不做任何花哨的事情,则不需要),您可能不需要它们。即便如此,您也可能会找到另一种方法来写下相同的内容,但仍会得到相同的结果。不过,使用它们可以更短(在某些情况下甚至更容易理解),所以我很高兴它是语言的一部分。
我还没有发现变量变量有很多用途,但是将变量用于方法会很方便,只要你在做什么是清楚的。例如,在一个简单的 REST 服务中,您可能会执行以下操作:
$method = $request->getMethod(); // 'post','get','put','delete'
try
{
$response = $resource->$method($request->getInput());
}
catch (BadMethodException $badMethod)
{
$response = $responseFactory->getError($badMethod);
}
有些人会争辩说,你可以用一个语句同样好地做到这一点switch
(你可以),但这种方式有助于扩展性(如果你决定添加另一种方法类型)并保持在资源上应用方法的抽象。