【发布时间】: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 中“锁定”变量。
- 我只想在这里记录一下;例如,我知道我可以使用
elseif来缓解此功能特有的问题之一,但我的问题更感兴趣的是与环境无关的解决方案,如果你愿意的话,这是一个包罗万象的解决方案。
【问题讨论】:
-
命名空间不能解决你的问题?自 5.3 以来,PHP 悲惨的命名空间变得更好和可用......几乎没有。
-
@edem - 虽然我已经充分利用了 5.3+ 的大多数可用功能,但命名空间是我没有采用的一种;我也无法想象在这种情况下这会有什么帮助。
-
最近所有的 tl;dr: 参考资料是怎么回事?
-
@Jared Farrish - 来自我,还是一般来说?我这样做只是因为在重新阅读我的问题后,我意识到它所问的内容非常冗长,而不是删除我应该总结的细节。
-
最好的方法就是直截了当地说出你的问题,然后说更多信息。留言与短信对话。
:)
标签: php include locking return scope