【问题标题】:Protecting variables from "include pollution" in PHP在 PHP 中保护变量免受“包含污染”
【发布时间】:2011-12-22 10:12:21
【问题描述】:

tl;dr: 有没有办法通过包含文件来防止更改(本质上锁定)在 include() 调用之前声明/定义的变量?另外,有点相关question


我想知道可以采取哪些措施来避免包含文件的变量污染。例如,给定这个花哨的小功能:

/**
 * Recursively loads values by include returns into
 * arguments of a callback
 * 
 * If $path is a file, only that file will be included.
 * If $path is a directory, all files in that directory
 * and all sub-directories will be included.
 * 
 * When a file is included, $callback is invoked passing
 * the returned value as an argument.
 *
 * @param string $path
 * @param callable $callback
 */
function load_values_recursive($path, $callback){
    $paths[] = path($path);
    while(!empty($paths)){
        $path = array_pop($paths);
        if(is_file($path)){
            if(true === $callback(include($path))){
                break;
            }
        }
        if(is_dir($path)){
            foreach(glob($path . '*') as $path){
                $paths[] = path($path);
            }
        }
    }
}

我知道它缺少一些类型检查和其他解释,让我们忽略这些。

无论如何,这个函数基本上会筛选一堆仅返回值的“数据”文件(通常是配置数组或路由表,但无论如何),然后调用传递的回调,以便返回值可以被过滤或排序或以某种方式使用。例如:

$values = array();
load_values_recursive('path/to/dir/', function($value) use(&$values){
    $values[] = $value;
});

path/to/dir/ 可能有几个文件遵循此模板:

return array(
    // yay, data!
);

当这些“配置”文件(或其他任何东西,试图保持这种可移植性和跨功能)开始包含基本逻辑时,我的问题就出现了。总是有可能污染函数本地的变量。例如,一个配置文件,为了聪明起见:

return array(
    'path_1' => $path = 'some/long/complicated/path/',
    'path_2' => $path . 'foo/',
    'path_3' => $path . 'bar/',
);

现在,鉴于 $path 恰好是相对于当前目录的可见目录,该函数将变得很不稳定:

// ...
if(is_file($path)){
    if(true === $callback(include($path))){ // path gets reset to 
        break;                              // some/long/complicated/path/
    }
}
if(is_dir($path)){                          // and gets added into the
    foreach(glob($path . '*') as $path){    // search tree
        $paths[] = path($path);
    }
}
// ...

这可能会产生最好的结果。我能想到的唯一1 解决方案是将include() 调用包装在另一个匿名函数中以更改范围:

// ...
if(true === call_user_func(function() use($callback, $path){
    return $callback($path);
})){
    break;
}
// ...

从而保护$path更重要的是$callback)不会在每次迭代中产生副作用。

我想知道在这种情况下是否存在一种更简单的方法来在 PHP 中“锁定”变量。

  1. 我只想在这里记录一下;例如,我知道我可以使用 elseif 来缓解此功能特有的问题之一,但我的问题更感兴趣的是与环境无关的解决方案,如果你愿意的话,这是一个包罗万象的解决方案。

【问题讨论】:

  • 命名空间不能解决你的问题?自 5.3 以来,PHP 悲惨的命名空间变得更好和可用......几乎没有。
  • @edem - 虽然我已经充分利用了 5.3+ 的大多数可用功能,但命名空间是我没有采用的一种;我也无法想象在这种情况下这会有什么帮助。
  • 最近所有的 tl;dr: 参考资料是怎么回事?
  • @Jared Farrish - 来自我,还是一般来说?我这样做只是因为在重新阅读我的问题后,我意识到它所问的内容非常冗长,而不是删除我应该总结的细节。
  • 最好的方法就是直截了当地说出你的问题,然后说更多信息。留言与短信对话。 :)

标签: php include locking return scope


【解决方案1】:

看看Giving PHP include()'d files parent variable scope,它有一个相当独特的方法来解决可以在这里使用的问题。

这相当于在包含之前取消设置所有已定义的变量,然后在之后重置它们。

它当然不优雅,但它会起作用。

【讨论】:

  • 谢谢@Allain Lalonde - 是的,我已经考虑过了;迄今为止最优雅的解决方案是我之前使用过很多次的解决方案;也就是说,将任何内容包装在自调用匿名函数中以创建新范围,并将 use() 包装在您需要的内容中。我想我之前可能问过一个问题,询问是否可以取消设置同时用作include() 参数的$path 变量,但无济于事。不过,这似乎是唯一的选择。
【解决方案2】:

我采用了以下解决方案来包括污染:

$value = call_user_func(function(){
    return include(func_get_arg(0));
}, $path);

$path 在包含时无处可见,而且看起来最优雅。当然,从包含的文件中调用 func_get_arg($i) 会产生传递的值,但是,好吧......

【讨论】:

  • 我收到了关于这个答案和另一个使用类似方法回答问题stackoverflow.com/a/8376780/409279-1;我只能假设它来自同一个人。你愿意详细说明为什么吗?我很好奇一个更好的选择,你肯定知道一个。
  • 显然来自 beelzebub 因为你是现代圣人!
  • 是的,这很好!但 100% 同意堆栈溢出需要以反对票强制评论!
  • @lol 我不认为 Stack Overflow 需要强制评论反对票;但是,如果您发现有问题,我认为无论您是否投反对票,发表评论都更具建设性。否则就像悄悄关灯,不经通知就离开房间一样。这是主观的,所以“嗯”。
猜你喜欢
  • 1970-01-01
  • 2014-06-02
  • 2023-04-09
  • 1970-01-01
  • 2018-02-02
  • 2013-09-26
  • 2013-01-22
  • 2013-04-24
  • 2013-02-19
相关资源
最近更新 更多