2011-11-04 58 views
4

TL;博士:有没有一种方法,以防止改动(主要锁定)声明/定义被包含的变量之前的include()呼叫,通过文件?此外,有点相关question保护变量“包括污染”在PHP


我想知道可以采取什么措施,以避免包括文件中的可变污染。例如,给定这个奇特的小功能:

/** 
* 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来缓解特定于此功能的问题之一,但是我的问题更关注环境不可知的解决方案,如果您愿意的话,这是一个全面的解决方案。
+0

命名空间不会解决您的问题?自5.3 PHP的悲惨命名空间变得更好和可用...几乎没有。 –

+0

@edem - 虽然我充分利用了大多数可用的5.3+功能,但名称空间是我没有采用的名称空间;我无法想象在这种情况下这将如何帮助。 – Dan

+0

什么是最近所有的** TL;博士:**参考最近? –

回答

1

我用以下解决方案去包括污染:

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

$path是无处在列入待观察,它似乎最优雅的。当然,从包含文件调用func_get_arg($i)将产生通过的值,但是,以及...

+0

我收到了一个** - 1 **这个答案和另一个使用类似的方法来回答这个问题http://stackoverflow.com/a/8376780/409279;我只是假设它来自同一个人。你愿意详细说明为什么吗?我很好奇一个更好的选择,当然你必须知道一个。 – Dan

+0

显然来自beelzebub,因为你是一个现代日! – lol

+1

@lol现在,downvotes现在不管了:-) – Dan

1

看看Giving PHP include()'d files parent variable scope它必须能够在此处使用的问题相当独特的方法。

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

它当然不是优雅的,但它会工作。

+0

谢谢@Allain Lalonde - 是的,这是我考虑过的;到目前为止,最优雅的解决方案就是我以前使用过很多次的解决方案;也就是说,无论在自我调用匿名函数中创建一个新的作用域,还是使用“use()”。我想我以前可能问过一个问题,询问是否可以取消同时用作include()的参数的$ path变量,但无济于事。这似乎是唯一的选择。 – Dan